1 /*
2 * Copyright 2014 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 #ifndef GrFragmentProcessor_DEFINED
9 #define GrFragmentProcessor_DEFINED
10
11 #include "include/private/SkMacros.h"
12 #include "include/private/SkSLSampleUsage.h"
13 #include "include/private/SkSLString.h"
14 #include "src/gpu/GrProcessor.h"
15 #include "src/gpu/glsl/GrGLSLUniformHandler.h"
16
17 #include <tuple>
18
19 class GrGLSLFPFragmentBuilder;
20 class GrGLSLProgramDataManager;
21 class GrPaint;
22 class GrPipeline;
23 class GrProcessorKeyBuilder;
24 class GrShaderCaps;
25 class GrSwizzle;
26 class GrTextureEffect;
27
28 /**
29 * Some fragment-processor creation methods have preconditions that might not be satisfied by the
30 * calling code. Those methods can return a `GrFPResult` from their factory methods. If creation
31 * succeeds, the new fragment processor is created and `success` is true. If a precondition is not
32 * met, `success` is set to false and the input FP is returned unchanged.
33 */
34 class GrFragmentProcessor;
35 using GrFPResult = std::tuple<bool /*success*/, std::unique_ptr<GrFragmentProcessor>>;
36
37 /** Provides custom fragment shader code. Fragment processors receive an input position and
38 produce an output color. They may contain uniforms and may have children fragment processors
39 that are sampled.
40 */
41 class GrFragmentProcessor : public GrProcessor {
42 public:
43 /**
44 * Every GrFragmentProcessor must be capable of creating a subclass of ProgramImpl. The
45 * ProgramImpl emits the fragment shader code that implements the GrFragmentProcessor, is
46 * attached to the generated backend API pipeline/program and used to extract uniform data from
47 * GrFragmentProcessor instances.
48 */
49 class ProgramImpl;
50
51 // Advanced Filter: Get Advanced Filter status, only GrSkSLFP overwrite isAFEnabled
isAFEnabled()52 virtual bool isAFEnabled() const
53 {
54 return false;
55 }
56
57 // Advanced Filter: Check Advanced Filter is enabled or not, by visiting its children recursively
58 // If one of its children enables AF, return true
59 bool checkAFRecursively() const;
60
61 /** Always returns 'color'. */
62 static std::unique_ptr<GrFragmentProcessor> MakeColor(SkPMColor4f color);
63
64 /**
65 * Returns the input color, modulated by the child's alpha.
66 *
67 * output = input * child.a
68 */
69 static std::unique_ptr<GrFragmentProcessor> MulInputByChildAlpha(
70 std::unique_ptr<GrFragmentProcessor> child);
71
72 /**
73 * Invokes child with an opaque version of the input color, then applies the input alpha to
74 * the result. Used to incorporate paint alpha to the evaluation of an SkShader tree FP.
75 */
76 static std::unique_ptr<GrFragmentProcessor> ApplyPaintAlpha(
77 std::unique_ptr<GrFragmentProcessor> child);
78
79 /**
80 * Returns a fragment processor that generates the passed-in color, modulated by the child's
81 * RGBA color. The child's input color will be the parent's fInputColor. (Pass a null FP to use
82 * the color from fInputColor instead of a child FP.)
83 */
84 static std::unique_ptr<GrFragmentProcessor> ModulateRGBA(
85 std::unique_ptr<GrFragmentProcessor> child, const SkPMColor4f& color);
86
87 /**
88 * Returns a parent fragment processor that adopts the passed fragment processor as a child.
89 * The parent will ignore its input color and instead feed the passed in color as input to the
90 * child.
91 */
92 static std::unique_ptr<GrFragmentProcessor> OverrideInput(std::unique_ptr<GrFragmentProcessor>,
93 const SkPMColor4f&);
94
95 /**
96 * Returns a parent fragment processor that adopts the passed fragment processor as a child.
97 * The parent will simply return the child's color, but disable the coverage-as-alpha
98 * optimization.
99 */
100 static std::unique_ptr<GrFragmentProcessor> DisableCoverageAsAlpha(
101 std::unique_ptr<GrFragmentProcessor>);
102
103 /**
104 * Returns a fragment processor which samples the passed-in fragment processor using
105 * `args.fDestColor` as its input color. Pass a null FP to access `args.fDestColor` directly.
106 * (This is only meaningful in contexts like blenders, which use a source and dest color.)
107 */
108 static std::unique_ptr<GrFragmentProcessor> UseDestColorAsInput(
109 std::unique_ptr<GrFragmentProcessor>);
110
111 /**
112 * Returns a fragment processor that calls the passed in fragment processor, and then swizzles
113 * the output.
114 */
115 static std::unique_ptr<GrFragmentProcessor> SwizzleOutput(std::unique_ptr<GrFragmentProcessor>,
116 const GrSwizzle&);
117
118 /**
119 * Returns a fragment processor that calls the passed in fragment processor, and then clamps
120 * the output to [0, 1].
121 */
122 static std::unique_ptr<GrFragmentProcessor> ClampOutput(std::unique_ptr<GrFragmentProcessor>);
123
124 /**
125 * Returns a fragment processor that composes two fragment processors `f` and `g` into f(g(x)).
126 * This is equivalent to running them in series (`g`, then `f`). This is not the same as
127 * transfer-mode composition; there is no blending step.
128 */
129 static std::unique_ptr<GrFragmentProcessor> Compose(std::unique_ptr<GrFragmentProcessor> f,
130 std::unique_ptr<GrFragmentProcessor> g);
131
132 /*
133 * Returns a fragment processor that calls the passed in fragment processor, then runs the
134 * resulting color through the supplied color matrix.
135 */
136 static std::unique_ptr<GrFragmentProcessor> ColorMatrix(
137 std::unique_ptr<GrFragmentProcessor> child,
138 const float matrix[20],
139 bool unpremulInput,
140 bool clampRGBOutput,
141 bool premulOutput);
142
143 /**
144 * Returns a fragment processor that reads back the color on the surface being painted; that is,
145 * sampling this will return the color of the pixel that is currently being painted over.
146 */
147 static std::unique_ptr<GrFragmentProcessor> SurfaceColor();
148
149 /**
150 * Returns a fragment processor that calls the passed in fragment processor, but evaluates it
151 * in device-space (rather than local space).
152 */
153 static std::unique_ptr<GrFragmentProcessor> DeviceSpace(std::unique_ptr<GrFragmentProcessor>);
154
155 /**
156 * "Shape" FPs, often used for clipping. Each one evaluates a particular kind of shape (rect,
157 * circle, ellipse), and modulates the coverage of that shape against the results of the input
158 * FP. GrClipEdgeType is used to select inverse/normal fill, and AA or non-AA edges.
159 */
160 static std::unique_ptr<GrFragmentProcessor> Rect(std::unique_ptr<GrFragmentProcessor>,
161 GrClipEdgeType,
162 SkRect);
163
164 static GrFPResult Circle(std::unique_ptr<GrFragmentProcessor>,
165 GrClipEdgeType,
166 SkPoint center,
167 float radius);
168
169 #ifdef SKIA_OHOS
170 static GrFPResult CircleSDF(std::unique_ptr<GrFragmentProcessor>,
171 GrClipEdgeType, SkPoint center, float radius);
172 #endif
173
174 static GrFPResult Ellipse(std::unique_ptr<GrFragmentProcessor>,
175 GrClipEdgeType,
176 SkPoint center,
177 SkPoint radii,
178 const GrShaderCaps&);
179
180 /**
181 * Returns a fragment processor that calls the passed in fragment processor, but ensures the
182 * entire program is compiled with high-precision types.
183 */
184 static std::unique_ptr<GrFragmentProcessor> HighPrecision(std::unique_ptr<GrFragmentProcessor>);
185
186 /**
187 * Makes a copy of this fragment processor that draws equivalently to the original.
188 * If the processor has child processors they are cloned as well.
189 */
190 virtual std::unique_ptr<GrFragmentProcessor> clone() const = 0;
191
192 // The FP this was registered with as a child function. This will be null if this is a root.
parent()193 const GrFragmentProcessor* parent() const { return fParent; }
194
195 std::unique_ptr<ProgramImpl> makeProgramImpl() const;
196
addToKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b)197 SK_ALWAYS_INLINE void addToKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
198 this->onAddToKey(caps, b);
199 for (const auto& child : fChildProcessors) {
200 if (child) {
201 child->addToKey(caps, b);
202 }
203 }
204 }
205
numChildProcessors()206 int numChildProcessors() const { return fChildProcessors.count(); }
207 int numNonNullChildProcessors() const;
208
childProcessor(int index)209 GrFragmentProcessor* childProcessor(int index) { return fChildProcessors[index].get(); }
childProcessor(int index)210 const GrFragmentProcessor* childProcessor(int index) const {
211 return fChildProcessors[index].get();
212 }
213
SkDEBUGCODE(bool isInstantiated ()const;)214 SkDEBUGCODE(bool isInstantiated() const;)
215
216 /** Do any of the FPs in this tree read back the color from the destination surface? */
217 bool willReadDstColor() const {
218 return SkToBool(fFlags & kWillReadDstColor_Flag);
219 }
220
221 /** Does the SkSL for this FP take two colors as its input arguments? */
isBlendFunction()222 bool isBlendFunction() const {
223 return SkToBool(fFlags & kIsBlendFunction_Flag);
224 }
225
226 /**
227 * True if this FP refers directly to the sample coordinate parameter of its function
228 * (e.g. uses EmitArgs::fSampleCoord in emitCode()). This is decided at FP-tree construction
229 * time and is not affected by lifting coords to varyings.
230 */
usesSampleCoordsDirectly()231 bool usesSampleCoordsDirectly() const {
232 return SkToBool(fFlags & kUsesSampleCoordsDirectly_Flag);
233 }
234
235 /**
236 * True if this FP uses its input coordinates or if any descendant FP uses them through a chain
237 * of non-explicit sample usages. (e.g. uses EmitArgs::fSampleCoord in emitCode()). This is
238 * decided at FP-tree construction time and is not affected by lifting coords to varyings.
239 */
usesSampleCoords()240 bool usesSampleCoords() const {
241 return SkToBool(fFlags & (kUsesSampleCoordsDirectly_Flag |
242 kUsesSampleCoordsIndirectly_Flag));
243 }
244
245 // The SampleUsage describing how this FP is invoked by its parent. This only reflects the
246 // immediate sampling from parent to this FP.
sampleUsage()247 const SkSL::SampleUsage& sampleUsage() const {
248 return fUsage;
249 }
250
251 /**
252 * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
253 * output under the following scenario:
254 * * all the color fragment processors report true to this query,
255 * * all the coverage fragment processors report true to this query,
256 * * the blend mode arithmetic allows for it it.
257 * To be compatible a fragment processor's output must be a modulation of its input color or
258 * alpha with a computed premultiplied color or alpha that is in 0..1 range. The computed color
259 * or alpha that is modulated against the input cannot depend on the input's alpha. The computed
260 * value cannot depend on the input's color channels unless it unpremultiplies the input color
261 * channels by the input alpha.
262 */
compatibleWithCoverageAsAlpha()263 bool compatibleWithCoverageAsAlpha() const {
264 return SkToBool(fFlags & kCompatibleWithCoverageAsAlpha_OptimizationFlag);
265 }
266
267 /**
268 * If this is true then all opaque input colors to the processor produce opaque output colors.
269 */
preservesOpaqueInput()270 bool preservesOpaqueInput() const {
271 return SkToBool(fFlags & kPreservesOpaqueInput_OptimizationFlag);
272 }
273
274 /**
275 * Tests whether given a constant input color the processor produces a constant output color
276 * (for all fragments). If true outputColor will contain the constant color produces for
277 * inputColor.
278 */
hasConstantOutputForConstantInput(SkPMColor4f inputColor,SkPMColor4f * outputColor)279 bool hasConstantOutputForConstantInput(SkPMColor4f inputColor, SkPMColor4f* outputColor) const {
280 if (fFlags & kConstantOutputForConstantInput_OptimizationFlag) {
281 *outputColor = this->constantOutputForConstantInput(inputColor);
282 return true;
283 }
284 return false;
285 }
hasConstantOutputForConstantInput()286 bool hasConstantOutputForConstantInput() const {
287 return SkToBool(fFlags & kConstantOutputForConstantInput_OptimizationFlag);
288 }
289
290 /** Returns true if this and other processor conservatively draw identically. It can only return
291 true when the two processor are of the same subclass (i.e. they return the same object from
292 from getFactory()).
293
294 A return value of true from isEqual() should not be used to test whether the processor would
295 generate the same shader code. To test for identical code generation use addToKey.
296 */
297 bool isEqual(const GrFragmentProcessor& that) const;
298
299 void visitProxies(const GrVisitProxyFunc&) const;
300
301 void visitTextureEffects(const std::function<void(const GrTextureEffect&)>&) const;
302
303 void visitWithImpls(const std::function<void(const GrFragmentProcessor&, ProgramImpl&)>&,
304 ProgramImpl&) const;
305
306 GrTextureEffect* asTextureEffect();
307 const GrTextureEffect* asTextureEffect() const;
308
309 #if GR_TEST_UTILS
310 // Generates debug info for this processor tree by recursively calling dumpInfo() on this
311 // processor and its children.
312 SkString dumpTreeInfo() const;
313 #endif
314
315 #ifdef SUPPORT_OPAQUE_OPTIMIZATION
getRRect()316 virtual SkRRect getRRect() const {
317 return SkRRect::MakeEmpty();
318 }
319 #endif
320
321 protected:
322 enum OptimizationFlags : uint32_t {
323 kNone_OptimizationFlags,
324 kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1,
325 kPreservesOpaqueInput_OptimizationFlag = 0x2,
326 kConstantOutputForConstantInput_OptimizationFlag = 0x4,
327 kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag |
328 kPreservesOpaqueInput_OptimizationFlag |
329 kConstantOutputForConstantInput_OptimizationFlag
330 };
SK_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)331 SK_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)
332
333 /**
334 * Can be used as a helper to decide which fragment processor OptimizationFlags should be set.
335 * This assumes that the subclass output color will be a modulation of the input color with a
336 * value read from a texture of the passed color type and that the texture contains
337 * premultiplied color or alpha values that are in range.
338 *
339 * Since there are multiple ways in which a sampler may have its coordinates clamped or wrapped,
340 * callers must determine on their own if the sampling uses a decal strategy in any way, in
341 * which case the texture may become transparent regardless of the color type.
342 */
343 static OptimizationFlags ModulateForSamplerOptFlags(SkAlphaType alphaType, bool samplingDecal) {
344 if (samplingDecal) {
345 return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
346 } else {
347 return ModulateForClampedSamplerOptFlags(alphaType);
348 }
349 }
350
351 // As above, but callers should somehow ensure or assert their sampler still uses clamping
ModulateForClampedSamplerOptFlags(SkAlphaType alphaType)352 static OptimizationFlags ModulateForClampedSamplerOptFlags(SkAlphaType alphaType) {
353 if (alphaType == kOpaque_SkAlphaType) {
354 return kCompatibleWithCoverageAsAlpha_OptimizationFlag |
355 kPreservesOpaqueInput_OptimizationFlag;
356 } else {
357 return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
358 }
359 }
360
GrFragmentProcessor(ClassID classID,OptimizationFlags optimizationFlags)361 GrFragmentProcessor(ClassID classID, OptimizationFlags optimizationFlags)
362 : INHERITED(classID), fFlags(optimizationFlags) {
363 SkASSERT((optimizationFlags & ~kAll_OptimizationFlags) == 0);
364 }
365
GrFragmentProcessor(const GrFragmentProcessor & src)366 explicit GrFragmentProcessor(const GrFragmentProcessor& src)
367 : INHERITED(src.classID()), fFlags(src.fFlags) {
368 this->cloneAndRegisterAllChildProcessors(src);
369 }
370
optimizationFlags()371 OptimizationFlags optimizationFlags() const {
372 return static_cast<OptimizationFlags>(kAll_OptimizationFlags & fFlags);
373 }
374
375 /** Useful when you can't call fp->optimizationFlags() on a base class object from a subclass.*/
ProcessorOptimizationFlags(const GrFragmentProcessor * fp)376 static OptimizationFlags ProcessorOptimizationFlags(const GrFragmentProcessor* fp) {
377 return fp ? fp->optimizationFlags() : kAll_OptimizationFlags;
378 }
379
380 /**
381 * This allows one subclass to access another subclass's implementation of
382 * constantOutputForConstantInput. It must only be called when
383 * hasConstantOutputForConstantInput() is known to be true.
384 */
ConstantOutputForConstantInput(const GrFragmentProcessor * fp,const SkPMColor4f & input)385 static SkPMColor4f ConstantOutputForConstantInput(const GrFragmentProcessor* fp,
386 const SkPMColor4f& input) {
387 if (fp) {
388 SkASSERT(fp->hasConstantOutputForConstantInput());
389 return fp->constantOutputForConstantInput(input);
390 } else {
391 return input;
392 }
393 }
394
395 /**
396 * FragmentProcessor subclasses call this from their constructor to register any child
397 * FragmentProcessors they have. This must be called AFTER all texture accesses and coord
398 * transforms have been added.
399 * This is for processors whose shader code will be composed of nested processors whose output
400 * colors will be combined somehow to produce its output color. Registering these child
401 * processors will allow the ProgramBuilder to automatically handle their transformed coords and
402 * texture accesses and mangle their uniform and output color names.
403 *
404 * The SampleUsage parameter describes all of the ways that the child is sampled by the parent.
405 */
406 void registerChild(std::unique_ptr<GrFragmentProcessor> child,
407 SkSL::SampleUsage sampleUsage = SkSL::SampleUsage::PassThrough());
408
409 /**
410 * This method takes an existing fragment processor, clones all of its children, and registers
411 * the clones as children of this fragment processor.
412 */
413 void cloneAndRegisterAllChildProcessors(const GrFragmentProcessor& src);
414
415 // FP implementations must call this function if their matching ProgramImpl's emitCode()
416 // function uses the EmitArgs::fSampleCoord variable in generated SkSL.
setUsesSampleCoordsDirectly()417 void setUsesSampleCoordsDirectly() {
418 fFlags |= kUsesSampleCoordsDirectly_Flag;
419 }
420
421 // FP implementations must set this flag if their ProgramImpl's emitCode() function calls
422 // dstColor() to read back the framebuffer.
setWillReadDstColor()423 void setWillReadDstColor() {
424 fFlags |= kWillReadDstColor_Flag;
425 }
426
427 // FP implementations must set this flag if their ProgramImpl's emitCode() function emits a
428 // blend function (taking two color inputs instead of just one).
setIsBlendFunction()429 void setIsBlendFunction() {
430 fFlags |= kIsBlendFunction_Flag;
431 }
432
mergeOptimizationFlags(OptimizationFlags flags)433 void mergeOptimizationFlags(OptimizationFlags flags) {
434 SkASSERT((flags & ~kAll_OptimizationFlags) == 0);
435 fFlags &= (flags | ~kAll_OptimizationFlags);
436 }
437
438 private:
constantOutputForConstantInput(const SkPMColor4f &)439 virtual SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& /* inputColor */) const {
440 SK_ABORT("Subclass must override this if advertising this optimization.");
441 }
442
443 /**
444 * Returns a new instance of the appropriate ProgramImpl subclass for the given
445 * GrFragmentProcessor. It will emit the appropriate code and live with the cached program
446 * to setup uniform data for each draw that uses the program.
447 */
448 virtual std::unique_ptr<ProgramImpl> onMakeProgramImpl() const = 0;
449
450 virtual void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
451
452 /**
453 * Subclass implements this to support isEqual(). It will only be called if it is known that
454 * the two processors are of the same subclass (i.e. have the same ClassID).
455 */
456 virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
457
458 enum PrivateFlags {
459 kFirstPrivateFlag = kAll_OptimizationFlags + 1,
460
461 // Propagates up the FP tree to either root or first explicit sample usage.
462 kUsesSampleCoordsIndirectly_Flag = kFirstPrivateFlag,
463
464 // Does not propagate at all. It means this FP uses its input sample coords in some way.
465 // Note passthrough and matrix sampling of children don't count as a usage of the coords.
466 // Because indirect sampling stops at an explicit sample usage it is imperative that a FP
467 // that calculates explicit coords for its children using its own sample coords sets this.
468 kUsesSampleCoordsDirectly_Flag = kFirstPrivateFlag << 1,
469
470 // Does not propagate at all.
471 kIsBlendFunction_Flag = kFirstPrivateFlag << 2,
472
473 // Propagates up the FP tree to the root.
474 kWillReadDstColor_Flag = kFirstPrivateFlag << 3,
475 };
476
477 SkSTArray<1, std::unique_ptr<GrFragmentProcessor>, true> fChildProcessors;
478 const GrFragmentProcessor* fParent = nullptr;
479 uint32_t fFlags = 0;
480 SkSL::SampleUsage fUsage;
481
482 using INHERITED = GrProcessor;
483 };
484
485 //////////////////////////////////////////////////////////////////////////////
486
487 class GrFragmentProcessor::ProgramImpl {
488 public:
489 ProgramImpl() = default;
490
491 virtual ~ProgramImpl() = default;
492
493 using UniformHandle = GrGLSLUniformHandler::UniformHandle;
494 using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
495
496 /** Called when the program stage should insert its code into the shaders. The code in each
497 shader will be in its own block ({}) and so locally scoped names will not collide across
498 stages.
499
500 @param fragBuilder Interface used to emit code in the shaders.
501 @param uniformHandler Interface used for accessing information about our uniforms
502 @param caps The capabilities of the GPU which will render this FP
503 @param fp The processor that generated this program stage.
504 @param inputColor A half4 that holds the input color to the stage in the FS (or the
505 source color, for blend processors). nullptr inputs are converted
506 to "half4(1.0)" (solid white) during construction.
507 TODO: Better system for communicating optimization info
508 (e.g. input color is solid white, trans black, known to be opaque,
509 etc.) that allows the processor to communicate back similar known
510 info about its output.
511 @param destColor A half4 that holds the dest color to the stage. Only meaningful
512 when the "is blend processor" FP flag is set.
513 @param sampleCoord The name of a local coord reference to a float2 variable. Only
514 meaningful when the "references sample coords" FP flag is set.
515 */
516 struct EmitArgs {
EmitArgsEmitArgs517 EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder,
518 GrGLSLUniformHandler* uniformHandler,
519 const GrShaderCaps* caps,
520 const GrFragmentProcessor& fp,
521 const char* inputColor,
522 const char* destColor,
523 const char* sampleCoord)
524 : fFragBuilder(fragBuilder)
525 , fUniformHandler(uniformHandler)
526 , fShaderCaps(caps)
527 , fFp(fp)
528 , fInputColor(inputColor ? inputColor : "half4(1.0)")
529 , fDestColor(destColor)
530 , fSampleCoord(sampleCoord) {}
531 GrGLSLFPFragmentBuilder* fFragBuilder;
532 GrGLSLUniformHandler* fUniformHandler;
533 const GrShaderCaps* fShaderCaps;
534 const GrFragmentProcessor& fFp;
535 const char* fInputColor;
536 const char* fDestColor;
537 const char* fSampleCoord;
538 };
539
540 virtual void emitCode(EmitArgs&) = 0;
541
542 // This does not recurse to any attached child processors. Recursing the entire processor tree
543 // is the responsibility of the caller.
544 void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor);
545
numChildProcessors()546 int numChildProcessors() const { return fChildProcessors.count(); }
547
childProcessor(int index)548 ProgramImpl* childProcessor(int index) const { return fChildProcessors[index].get(); }
549
setFunctionName(SkString name)550 void setFunctionName(SkString name) {
551 SkASSERT(fFunctionName.isEmpty());
552 fFunctionName = std::move(name);
553 }
554
functionName()555 const char* functionName() const {
556 SkASSERT(!fFunctionName.isEmpty());
557 return fFunctionName.c_str();
558 }
559
560 // Invoke the child with the default input and destination colors (solid white)
561 inline SkString invokeChild(int childIndex,
562 EmitArgs& parentArgs,
563 SkSL::String skslCoords = "") {
564 return this->invokeChild(childIndex,
565 /*inputColor=*/nullptr,
566 /*destColor=*/nullptr,
567 parentArgs,
568 skslCoords);
569 }
570
invokeChildWithMatrix(int childIndex,EmitArgs & parentArgs)571 inline SkString invokeChildWithMatrix(int childIndex, EmitArgs& parentArgs) {
572 return this->invokeChildWithMatrix(childIndex,
573 /*inputColor=*/nullptr,
574 /*destColor=*/nullptr,
575 parentArgs);
576 }
577
578 // Invoke the child with the default destination color (solid white)
579 inline SkString invokeChild(int childIndex,
580 const char* inputColor,
581 EmitArgs& parentArgs,
582 SkSL::String skslCoords = "") {
583 return this->invokeChild(childIndex,
584 inputColor,
585 /*destColor=*/nullptr,
586 parentArgs,
587 skslCoords);
588 }
589
invokeChildWithMatrix(int childIndex,const char * inputColor,EmitArgs & parentArgs)590 inline SkString invokeChildWithMatrix(int childIndex,
591 const char* inputColor,
592 EmitArgs& parentArgs) {
593 return this->invokeChildWithMatrix(childIndex,
594 inputColor,
595 /*destColor=*/nullptr,
596 parentArgs);
597 }
598
599 /** Invokes a child proc in its own scope. Pass in the parent's EmitArgs and invokeChild will
600 * automatically extract the coords and samplers of that child and pass them on to the child's
601 * emitCode(). Also, any uniforms or functions emitted by the child will have their names
602 * mangled to prevent redefinitions. The returned string contains the output color (as a call
603 * to the child's helper function). It is legal to pass nullptr as inputColor, since all
604 * fragment processors are required to work without an input color.
605 *
606 * When skslCoords is empty, the child is invoked at the sample coordinates from parentArgs.
607 * When skslCoords is not empty, is must be an SkSL expression that evaluates to a float2.
608 * That expression is passed to the child's processor function as the "_coords" argument.
609 */
610 SkString invokeChild(int childIndex,
611 const char* inputColor,
612 const char* destColor,
613 EmitArgs& parentArgs,
614 SkSL::String skslCoords = "");
615
616 /**
617 * As invokeChild, but transforms the coordinates according to the matrix expression attached
618 * to the child's SampleUsage object. This is only valid if the child is sampled with a
619 * const-uniform matrix.
620 */
621 SkString invokeChildWithMatrix(int childIndex,
622 const char* inputColor,
623 const char* destColor,
624 EmitArgs& parentArgs);
625
626 /**
627 * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of
628 * GLSLFPS. If initialized with an array color followed by coverage processors installed in a
629 * program thenthe iteration order will agree with a GrFragmentProcessor::Iter initialized with
630 * a GrPipeline that produces the same program key.
631 */
632 class Iter {
633 public:
634 Iter(std::unique_ptr<ProgramImpl> fps[], int cnt);
Iter(ProgramImpl & fp)635 Iter(ProgramImpl& fp) { fFPStack.push_back(&fp); }
636
637 ProgramImpl& operator*() const;
638 ProgramImpl* operator->() const;
639 Iter& operator++();
640 operator bool() const { return !fFPStack.empty(); }
641
642 // Because each iterator carries a stack we want to avoid copies.
643 Iter(const Iter&) = delete;
644 Iter& operator=(const Iter&) = delete;
645
646 private:
647 SkSTArray<4, ProgramImpl*, true> fFPStack;
648 };
649
650 private:
651 /**
652 * A ProgramImpl instance can be reused with any GrFragmentProcessor that produces the same
653 * the same key; this function reads data from a GrFragmentProcessor and uploads any
654 * uniform variables required by the shaders created in emitCode(). The GrFragmentProcessor
655 * parameter is guaranteed to be of the same type that created this ProgramImpl and
656 * to have an identical key as the one that created this ProgramImpl.
657 */
onSetData(const GrGLSLProgramDataManager &,const GrFragmentProcessor &)658 virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {}
659
660 // The (mangled) name of our entry-point function
661 SkString fFunctionName;
662
663 SkTArray<std::unique_ptr<ProgramImpl>, true> fChildProcessors;
664
665 friend class GrFragmentProcessor;
666 };
667
668 //////////////////////////////////////////////////////////////////////////////
669
SK_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)670 SK_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)
671
672 static inline GrFPResult GrFPFailure(std::unique_ptr<GrFragmentProcessor> fp) {
673 return {false, std::move(fp)};
674 }
GrFPSuccess(std::unique_ptr<GrFragmentProcessor> fp)675 static inline GrFPResult GrFPSuccess(std::unique_ptr<GrFragmentProcessor> fp) {
676 SkASSERT(fp);
677 return {true, std::move(fp)};
678 }
679
680 #endif
681