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 "src/gpu/GrCoordTransform.h" |
9 | #include "src/gpu/GrFragmentProcessor.h" |
10 | #include "src/gpu/GrPipeline.h" |
11 | #include "src/gpu/GrProcessorAnalysis.h" |
12 | #include "src/gpu/effects/GrXfermodeFragmentProcessor.h" |
13 | #include "src/gpu/effects/generated/GrClampFragmentProcessor.h" |
14 | #include "src/gpu/effects/generated/GrConstColorProcessor.h" |
15 | #include "src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h" |
16 | #include "src/gpu/effects/generated/GrPremulInputFragmentProcessor.h" |
17 | #include "src/gpu/glsl/GrGLSLFragmentProcessor.h" |
18 | #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" |
19 | #include "src/gpu/glsl/GrGLSLProgramDataManager.h" |
20 | #include "src/gpu/glsl/GrGLSLUniformHandler.h" |
21 | |
22 | bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that) const { |
23 | if (this->classID() != that.classID()) { |
24 | return false; |
25 | } |
26 | if (this->numTextureSamplers() != that.numTextureSamplers()) { |
27 | return false; |
28 | } |
29 | for (int i = 0; i < this->numTextureSamplers(); ++i) { |
30 | if (this->textureSampler(i) != that.textureSampler(i)) { |
31 | return false; |
32 | } |
33 | } |
34 | if (!this->hasSameTransforms(that)) { |
35 | return false; |
36 | } |
37 | if (!this->onIsEqual(that)) { |
38 | return false; |
39 | } |
40 | if (this->numChildProcessors() != that.numChildProcessors()) { |
41 | return false; |
42 | } |
43 | for (int i = 0; i < this->numChildProcessors(); ++i) { |
44 | if (!this->childProcessor(i).isEqual(that.childProcessor(i))) { |
45 | return false; |
46 | } |
47 | } |
48 | return true; |
49 | } |
50 | |
51 | void GrFragmentProcessor::visitProxies(const GrOp::VisitProxyFunc& func) { |
52 | for (auto [sampler, fp] : FPTextureSamplerRange(*this)) { |
53 | bool mipped = (GrSamplerState::Filter::kMipMap == sampler.samplerState().filter()); |
54 | func(sampler.view().proxy(), GrMipMapped(mipped)); |
55 | } |
56 | } |
57 | |
58 | GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const { |
59 | GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance(); |
60 | glFragProc->fChildProcessors.push_back_n(fChildProcessors.count()); |
61 | for (int i = 0; i < fChildProcessors.count(); ++i) { |
62 | glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLSLInstance(); |
63 | } |
64 | return glFragProc; |
65 | } |
66 | |
67 | const GrFragmentProcessor::TextureSampler& GrFragmentProcessor::textureSampler(int i) const { |
68 | SkASSERT(i >= 0 && i < fTextureSamplerCnt); |
69 | return this->onTextureSampler(i); |
70 | } |
71 | |
72 | void GrFragmentProcessor::addCoordTransform(GrCoordTransform* transform) { |
73 | fCoordTransforms.push_back(transform); |
74 | fFlags |= kHasCoordTransforms_Flag; |
75 | } |
76 | |
77 | #ifdef SK_DEBUG |
78 | bool GrFragmentProcessor::isInstantiated() const { |
79 | for (int i = 0; i < fTextureSamplerCnt; ++i) { |
80 | if (!this->textureSampler(i).isInstantiated()) { |
81 | return false; |
82 | } |
83 | } |
84 | |
85 | for (int i = 0; i < this->numChildProcessors(); ++i) { |
86 | if (!this->childProcessor(i).isInstantiated()) { |
87 | return false; |
88 | } |
89 | } |
90 | |
91 | return true; |
92 | } |
93 | #endif |
94 | |
95 | int GrFragmentProcessor::registerChildProcessor(std::unique_ptr<GrFragmentProcessor> child) { |
96 | if (child->fFlags & kHasCoordTransforms_Flag) { |
97 | fFlags |= kHasCoordTransforms_Flag; |
98 | } |
99 | fRequestedFeatures |= child->fRequestedFeatures; |
100 | |
101 | int index = fChildProcessors.count(); |
102 | fChildProcessors.push_back(std::move(child)); |
103 | |
104 | return index; |
105 | } |
106 | |
107 | bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const { |
108 | if (this->numCoordTransforms() != that.numCoordTransforms()) { |
109 | return false; |
110 | } |
111 | int count = this->numCoordTransforms(); |
112 | for (int i = 0; i < count; ++i) { |
113 | if (!this->coordTransform(i).hasSameEffectiveMatrix(that.coordTransform(i))) { |
114 | return false; |
115 | } |
116 | } |
117 | return true; |
118 | } |
119 | |
120 | std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MulChildByInputAlpha( |
121 | std::unique_ptr<GrFragmentProcessor> fp) { |
122 | if (!fp) { |
123 | return nullptr; |
124 | } |
125 | return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp), SkBlendMode::kDstIn); |
126 | } |
127 | |
128 | std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MulInputByChildAlpha( |
129 | std::unique_ptr<GrFragmentProcessor> fp) { |
130 | if (!fp) { |
131 | return nullptr; |
132 | } |
133 | return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp), SkBlendMode::kSrcIn); |
134 | } |
135 | |
136 | std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::PremulInput( |
137 | std::unique_ptr<GrFragmentProcessor> fp) { |
138 | if (!fp) { |
139 | return nullptr; |
140 | } |
141 | std::unique_ptr<GrFragmentProcessor> fpPipeline[] = { GrPremulInputFragmentProcessor::Make(), |
142 | std::move(fp) }; |
143 | return GrFragmentProcessor::RunInSeries(fpPipeline, 2); |
144 | } |
145 | |
146 | std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::ClampPremulOutput( |
147 | std::unique_ptr<GrFragmentProcessor> fp) { |
148 | if (!fp) { |
149 | return nullptr; |
150 | } |
151 | std::unique_ptr<GrFragmentProcessor> fpPipeline[] = { |
152 | std::move(fp), |
153 | GrClampFragmentProcessor::Make(true) |
154 | }; |
155 | return GrFragmentProcessor::RunInSeries(fpPipeline, 2); |
156 | } |
157 | |
158 | std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::SwizzleOutput( |
159 | std::unique_ptr<GrFragmentProcessor> fp, const GrSwizzle& swizzle) { |
160 | class SwizzleFragmentProcessor : public GrFragmentProcessor { |
161 | public: |
162 | static std::unique_ptr<GrFragmentProcessor> Make(const GrSwizzle& swizzle) { |
163 | return std::unique_ptr<GrFragmentProcessor>(new SwizzleFragmentProcessor(swizzle)); |
164 | } |
165 | |
166 | const char* name() const override { return "Swizzle" ; } |
167 | const GrSwizzle& swizzle() const { return fSwizzle; } |
168 | |
169 | std::unique_ptr<GrFragmentProcessor> clone() const override { return Make(fSwizzle); } |
170 | |
171 | private: |
172 | SwizzleFragmentProcessor(const GrSwizzle& swizzle) |
173 | : INHERITED(kSwizzleFragmentProcessor_ClassID, kAll_OptimizationFlags) |
174 | , fSwizzle(swizzle) {} |
175 | |
176 | GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { |
177 | class GLFP : public GrGLSLFragmentProcessor { |
178 | public: |
179 | void emitCode(EmitArgs& args) override { |
180 | const SwizzleFragmentProcessor& sfp = args.fFp.cast<SwizzleFragmentProcessor>(); |
181 | const GrSwizzle& swizzle = sfp.swizzle(); |
182 | GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; |
183 | |
184 | fragBuilder->codeAppendf("%s = %s.%s;" , |
185 | args.fOutputColor, args.fInputColor, swizzle.asString().c_str()); |
186 | } |
187 | }; |
188 | return new GLFP; |
189 | } |
190 | |
191 | void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override { |
192 | b->add32(fSwizzle.asKey()); |
193 | } |
194 | |
195 | bool onIsEqual(const GrFragmentProcessor& other) const override { |
196 | const SwizzleFragmentProcessor& sfp = other.cast<SwizzleFragmentProcessor>(); |
197 | return fSwizzle == sfp.fSwizzle; |
198 | } |
199 | |
200 | SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override { |
201 | return fSwizzle.applyTo(input); |
202 | } |
203 | |
204 | GrSwizzle fSwizzle; |
205 | |
206 | typedef GrFragmentProcessor INHERITED; |
207 | }; |
208 | |
209 | if (!fp) { |
210 | return nullptr; |
211 | } |
212 | if (GrSwizzle::RGBA() == swizzle) { |
213 | return fp; |
214 | } |
215 | std::unique_ptr<GrFragmentProcessor> fpPipeline[] = { std::move(fp), |
216 | SwizzleFragmentProcessor::Make(swizzle) }; |
217 | return GrFragmentProcessor::RunInSeries(fpPipeline, 2); |
218 | } |
219 | |
220 | std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::MakeInputPremulAndMulByOutput( |
221 | std::unique_ptr<GrFragmentProcessor> fp) { |
222 | class PremulFragmentProcessor : public GrFragmentProcessor { |
223 | public: |
224 | static std::unique_ptr<GrFragmentProcessor> Make( |
225 | std::unique_ptr<GrFragmentProcessor> processor) { |
226 | return std::unique_ptr<GrFragmentProcessor>( |
227 | new PremulFragmentProcessor(std::move(processor))); |
228 | } |
229 | |
230 | const char* name() const override { return "Premultiply" ; } |
231 | |
232 | std::unique_ptr<GrFragmentProcessor> clone() const override { |
233 | return Make(this->childProcessor(0).clone()); |
234 | } |
235 | |
236 | private: |
237 | PremulFragmentProcessor(std::unique_ptr<GrFragmentProcessor> processor) |
238 | : INHERITED(kPremulFragmentProcessor_ClassID, OptFlags(processor.get())) { |
239 | this->registerChildProcessor(std::move(processor)); |
240 | } |
241 | |
242 | GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { |
243 | class GLFP : public GrGLSLFragmentProcessor { |
244 | public: |
245 | void emitCode(EmitArgs& args) override { |
246 | GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; |
247 | SkString temp = this->invokeChild(0, args); |
248 | fragBuilder->codeAppendf("%s = %s;" , args.fOutputColor, temp.c_str()); |
249 | fragBuilder->codeAppendf("%s.rgb *= %s.rgb;" , args.fOutputColor, |
250 | args.fInputColor); |
251 | fragBuilder->codeAppendf("%s *= %s.a;" , args.fOutputColor, args.fInputColor); |
252 | } |
253 | }; |
254 | return new GLFP; |
255 | } |
256 | |
257 | void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {} |
258 | |
259 | bool onIsEqual(const GrFragmentProcessor&) const override { return true; } |
260 | |
261 | static OptimizationFlags OptFlags(const GrFragmentProcessor* inner) { |
262 | OptimizationFlags flags = kNone_OptimizationFlags; |
263 | if (inner->preservesOpaqueInput()) { |
264 | flags |= kPreservesOpaqueInput_OptimizationFlag; |
265 | } |
266 | if (inner->hasConstantOutputForConstantInput()) { |
267 | flags |= kConstantOutputForConstantInput_OptimizationFlag; |
268 | } |
269 | return flags; |
270 | } |
271 | |
272 | SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override { |
273 | SkPMColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0), |
274 | SK_PMColor4fWHITE); |
275 | SkPMColor4f premulInput = SkColor4f{ input.fR, input.fG, input.fB, input.fA }.premul(); |
276 | return premulInput * childColor; |
277 | } |
278 | |
279 | typedef GrFragmentProcessor INHERITED; |
280 | }; |
281 | if (!fp) { |
282 | return nullptr; |
283 | } |
284 | return PremulFragmentProcessor::Make(std::move(fp)); |
285 | } |
286 | |
287 | ////////////////////////////////////////////////////////////////////////////// |
288 | |
289 | std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::OverrideInput( |
290 | std::unique_ptr<GrFragmentProcessor> fp, const SkPMColor4f& color, bool useUniform) { |
291 | if (!fp) { |
292 | return nullptr; |
293 | } |
294 | return GrOverrideInputFragmentProcessor::Make(std::move(fp), color, useUniform); |
295 | } |
296 | |
297 | std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::RunInSeries( |
298 | std::unique_ptr<GrFragmentProcessor> series[], int cnt) { |
299 | class SeriesFragmentProcessor : public GrFragmentProcessor { |
300 | public: |
301 | static std::unique_ptr<GrFragmentProcessor> Make( |
302 | std::unique_ptr<GrFragmentProcessor>* children, int cnt) { |
303 | return std::unique_ptr<GrFragmentProcessor>(new SeriesFragmentProcessor(children, cnt)); |
304 | } |
305 | |
306 | const char* name() const override { return "Series" ; } |
307 | |
308 | std::unique_ptr<GrFragmentProcessor> clone() const override { |
309 | SkSTArray<4, std::unique_ptr<GrFragmentProcessor>> children(this->numChildProcessors()); |
310 | for (int i = 0; i < this->numChildProcessors(); ++i) { |
311 | if (!children.push_back(this->childProcessor(i).clone())) { |
312 | return nullptr; |
313 | } |
314 | } |
315 | return Make(children.begin(), this->numChildProcessors()); |
316 | } |
317 | |
318 | private: |
319 | GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { |
320 | class GLFP : public GrGLSLFragmentProcessor { |
321 | public: |
322 | void emitCode(EmitArgs& args) override { |
323 | // First guy's input might be nil. |
324 | SkString result = this->invokeChild(0, args.fInputColor, args); |
325 | for (int i = 1; i < this->numChildProcessors(); ++i) { |
326 | result = this->invokeChild(i, result.c_str(), args); |
327 | } |
328 | // Copy last output to our output variable |
329 | args.fFragBuilder->codeAppendf("%s = %s;" , args.fOutputColor, result.c_str()); |
330 | } |
331 | }; |
332 | return new GLFP; |
333 | } |
334 | |
335 | SeriesFragmentProcessor(std::unique_ptr<GrFragmentProcessor>* children, int cnt) |
336 | : INHERITED(kSeriesFragmentProcessor_ClassID, OptFlags(children, cnt)) { |
337 | SkASSERT(cnt > 1); |
338 | for (int i = 0; i < cnt; ++i) { |
339 | this->registerChildProcessor(std::move(children[i])); |
340 | } |
341 | } |
342 | |
343 | static OptimizationFlags OptFlags(std::unique_ptr<GrFragmentProcessor>* children, int cnt) { |
344 | OptimizationFlags flags = kAll_OptimizationFlags; |
345 | for (int i = 0; i < cnt && flags != kNone_OptimizationFlags; ++i) { |
346 | flags &= children[i]->optimizationFlags(); |
347 | } |
348 | return flags; |
349 | } |
350 | void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {} |
351 | |
352 | bool onIsEqual(const GrFragmentProcessor&) const override { return true; } |
353 | |
354 | SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override { |
355 | SkPMColor4f color = inColor; |
356 | int childCnt = this->numChildProcessors(); |
357 | for (int i = 0; i < childCnt; ++i) { |
358 | color = ConstantOutputForConstantInput(this->childProcessor(i), color); |
359 | } |
360 | return color; |
361 | } |
362 | |
363 | typedef GrFragmentProcessor INHERITED; |
364 | }; |
365 | |
366 | if (!cnt) { |
367 | return nullptr; |
368 | } |
369 | if (1 == cnt) { |
370 | return std::move(series[0]); |
371 | } |
372 | // Run the through the series, do the invariant output processing, and look for eliminations. |
373 | GrProcessorAnalysisColor inputColor; |
374 | inputColor.setToUnknown(); |
375 | GrColorFragmentProcessorAnalysis info(inputColor, series, cnt); |
376 | SkTArray<std::unique_ptr<GrFragmentProcessor>> replacementSeries; |
377 | SkPMColor4f knownColor; |
378 | int leadingFPsToEliminate = info.initialProcessorsToEliminate(&knownColor); |
379 | if (leadingFPsToEliminate) { |
380 | std::unique_ptr<GrFragmentProcessor> colorFP( |
381 | GrConstColorProcessor::Make(knownColor, GrConstColorProcessor::InputMode::kIgnore)); |
382 | if (leadingFPsToEliminate == cnt) { |
383 | return colorFP; |
384 | } |
385 | cnt = cnt - leadingFPsToEliminate + 1; |
386 | replacementSeries.reserve(cnt); |
387 | replacementSeries.emplace_back(std::move(colorFP)); |
388 | for (int i = 0; i < cnt - 1; ++i) { |
389 | replacementSeries.emplace_back(std::move(series[leadingFPsToEliminate + i])); |
390 | } |
391 | series = replacementSeries.begin(); |
392 | } |
393 | return SeriesFragmentProcessor::Make(series, cnt); |
394 | } |
395 | |
396 | ////////////////////////////////////////////////////////////////////////////// |
397 | |
398 | GrFragmentProcessor::CIter::CIter(const GrPaint& paint) { |
399 | for (int i = paint.numCoverageFragmentProcessors() - 1; i >= 0; --i) { |
400 | fFPStack.push_back(paint.getCoverageFragmentProcessor(i)); |
401 | } |
402 | for (int i = paint.numColorFragmentProcessors() - 1; i >= 0; --i) { |
403 | fFPStack.push_back(paint.getColorFragmentProcessor(i)); |
404 | } |
405 | } |
406 | |
407 | GrFragmentProcessor::CIter::CIter(const GrProcessorSet& set) { |
408 | for (int i = set.numCoverageFragmentProcessors() - 1; i >= 0; --i) { |
409 | fFPStack.push_back(set.coverageFragmentProcessor(i)); |
410 | } |
411 | for (int i = set.numColorFragmentProcessors() - 1; i >= 0; --i) { |
412 | fFPStack.push_back(set.colorFragmentProcessor(i)); |
413 | } |
414 | } |
415 | |
416 | GrFragmentProcessor::CIter::CIter(const GrPipeline& pipeline) { |
417 | for (int i = pipeline.numFragmentProcessors() - 1; i >= 0; --i) { |
418 | fFPStack.push_back(&pipeline.getFragmentProcessor(i)); |
419 | } |
420 | } |
421 | |
422 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
423 | |
424 | GrFragmentProcessor::TextureSampler::TextureSampler(GrSurfaceProxyView view, |
425 | GrSamplerState samplerState) |
426 | : fView(std::move(view)), fSamplerState(samplerState) { |
427 | GrSurfaceProxy* proxy = this->proxy(); |
428 | fSamplerState.setFilterMode( |
429 | std::min(samplerState.filter(), |
430 | GrTextureProxy::HighestFilterMode(proxy->backendFormat().textureType()))); |
431 | } |
432 | |
433 | #if GR_TEST_UTILS |
434 | void GrFragmentProcessor::TextureSampler::set(GrSurfaceProxyView view, |
435 | GrSamplerState samplerState) { |
436 | SkASSERT(view.proxy()->asTextureProxy()); |
437 | fView = std::move(view); |
438 | fSamplerState = samplerState; |
439 | |
440 | fSamplerState.setFilterMode( |
441 | std::min(samplerState.filter(), |
442 | GrTextureProxy::HighestFilterMode(this->proxy()->backendFormat().textureType()))); |
443 | } |
444 | #endif |
445 | |