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