blob: d7011f826c84bb1e0eb3a246cdd1f363208bd73f [file] [log] [blame]
bsalomon6251d172014-10-15 10:50:36 -07001/*
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 "GrProcessor.h"
12
13class GrCoordTransform;
jvanverthe9c0fc62015-04-29 11:18:05 -070014class GrGLSLCaps;
egdaniel64c47282015-11-13 06:54:19 -080015class GrGLSLFragmentProcessor;
bsalomonc21b09e2015-08-28 18:46:56 -070016class GrInvariantOutput;
bsalomona624bf32016-09-20 09:12:47 -070017class GrPipeline;
joshualitteb2a6762014-12-04 11:35:33 -080018class GrProcessorKeyBuilder;
bsalomon6251d172014-10-15 10:50:36 -070019
20/** Provides custom fragment shader code. Fragment processors receive an input color (vec4f) and
21 produce an output color. They may reference textures and uniforms. They may use
22 GrCoordTransforms to receive a transformation of the local coordinates that map from local space
23 to the fragment being processed.
24 */
25class GrFragmentProcessor : public GrProcessor {
26public:
bsalomon87ba62e2015-09-22 06:41:59 -070027 /**
28 * In many instances (e.g. SkShader::asFragmentProcessor() implementations) it is desirable to
29 * only consider the input color's alpha. However, there is a competing desire to have reusable
30 * GrFragmentProcessor subclasses that can be used in other scenarios where the entire input
31 * color is considered. This function exists to filter the input color and pass it to a FP. It
32 * does so by returning a parent FP that multiplies the passed in FPs output by the parent's
33 * input alpha. The passed in FP will not receive an input color.
34 */
bungeman06ca8ec2016-06-09 08:01:03 -070035 static sk_sp<GrFragmentProcessor> MulOutputByInputAlpha(sk_sp<GrFragmentProcessor>);
bsalomonf1b7a1d2015-09-28 06:26:28 -070036
37 /**
38 * Similar to the above but it modulates the output r,g,b of the child processor by the input
39 * rgb and then multiplies all the components by the input alpha. This effectively modulates
40 * the child processor's premul color by a unpremul'ed input and produces a premul output
41 */
bungeman06ca8ec2016-06-09 08:01:03 -070042 static sk_sp<GrFragmentProcessor> MulOutputByInputUnpremulColor(sk_sp<GrFragmentProcessor>);
bsalomonf1b7a1d2015-09-28 06:26:28 -070043
44 /**
bsalomone25eea42015-09-29 06:38:55 -070045 * Returns a parent fragment processor that adopts the passed fragment processor as a child.
46 * The parent will ignore its input color and instead feed the passed in color as input to the
47 * child.
bsalomonf1b7a1d2015-09-28 06:26:28 -070048 */
brianosman4cea3b92016-09-08 09:33:50 -070049 static sk_sp<GrFragmentProcessor> OverrideInput(sk_sp<GrFragmentProcessor>, GrColor4f);
bsalomon87ba62e2015-09-22 06:41:59 -070050
bsalomone25eea42015-09-29 06:38:55 -070051 /**
dvonbeckc526da92016-07-20 11:20:30 -070052 * Returns a fragment processor that premuls the input before calling the passed in fragment
53 * processor.
54 */
55 static sk_sp<GrFragmentProcessor> PremulInput(sk_sp<GrFragmentProcessor>);
56
57 /**
bsalomone25eea42015-09-29 06:38:55 -070058 * Returns a fragment processor that runs the passed in array of fragment processors in a
59 * series. The original input is passed to the first, the first's output is passed to the
60 * second, etc. The output of the returned processor is the output of the last processor of the
61 * series.
bungeman06ca8ec2016-06-09 08:01:03 -070062 *
63 * The array elements with be moved.
bsalomone25eea42015-09-29 06:38:55 -070064 */
bungeman06ca8ec2016-06-09 08:01:03 -070065 static sk_sp<GrFragmentProcessor> RunInSeries(sk_sp<GrFragmentProcessor>*, int cnt);
bsalomone25eea42015-09-29 06:38:55 -070066
bsalomon6251d172014-10-15 10:50:36 -070067 GrFragmentProcessor()
68 : INHERITED()
dvonbeck9b03e7b2016-08-01 11:01:56 -070069 , fUsesDistanceVectorField(false)
bsalomonb58a2b42016-09-26 06:55:02 -070070 , fUsesLocalCoords(false) {}
bsalomon6251d172014-10-15 10:50:36 -070071
bsalomonac856c92015-08-27 06:30:17 -070072 ~GrFragmentProcessor() override;
73
egdaniel57d3b032015-11-13 11:57:27 -080074 GrGLSLFragmentProcessor* createGLSLInstance() const;
joshualitteb2a6762014-12-04 11:35:33 -080075
egdaniel57d3b032015-11-13 11:57:27 -080076 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
77 this->onGetGLSLProcessorKey(caps, b);
wangyix4b3050b2015-08-04 07:59:37 -070078 for (int i = 0; i < fChildProcessors.count(); ++i) {
egdaniel57d3b032015-11-13 11:57:27 -080079 fChildProcessors[i]->getGLSLProcessorKey(caps, b);
wangyix4b3050b2015-08-04 07:59:37 -070080 }
81 }
82
bsalomona624bf32016-09-20 09:12:47 -070083 int numCoordTransforms() const { return fCoordTransforms.count(); }
bsalomon6251d172014-10-15 10:50:36 -070084
85 /** Returns the coordinate transformation at index. index must be valid according to
86 numTransforms(). */
87 const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
88
joshualittabb52a12015-01-13 15:02:10 -080089 const SkTArray<const GrCoordTransform*, true>& coordTransforms() const {
90 return fCoordTransforms;
91 }
92
wangyix4b3050b2015-08-04 07:59:37 -070093 int numChildProcessors() const { return fChildProcessors.count(); }
94
bsalomonac856c92015-08-27 06:30:17 -070095 const GrFragmentProcessor& childProcessor(int index) const { return *fChildProcessors[index]; }
wangyix4b3050b2015-08-04 07:59:37 -070096
joshualitt290c09b2014-12-19 13:45:20 -080097 /** Do any of the coordtransforms for this processor require local coords? */
98 bool usesLocalCoords() const { return fUsesLocalCoords; }
99
dvonbeck9b03e7b2016-08-01 11:01:56 -0700100 /** Does this FP need a vector to the nearest edge? */
101 bool usesDistanceVectorField() const { return fUsesDistanceVectorField; }
102
joshualitteb2a6762014-12-04 11:35:33 -0800103 /** Returns true if this and other processor conservatively draw identically. It can only return
104 true when the two processor are of the same subclass (i.e. they return the same object from
bsalomon6251d172014-10-15 10:50:36 -0700105 from getFactory()).
106
joshualitteb2a6762014-12-04 11:35:33 -0800107 A return value of true from isEqual() should not be used to test whether the processor would
egdaniel57d3b032015-11-13 11:57:27 -0800108 generate the same shader code. To test for identical code generation use getGLSLProcessorKey
109 */
bsalomon7312ff82016-09-12 08:55:38 -0700110 bool isEqual(const GrFragmentProcessor& that) const;
bsalomon6251d172014-10-15 10:50:36 -0700111
joshualitt56995b52014-12-11 15:44:02 -0800112 /**
113 * This function is used to perform optimizations. When called the invarientOuput param
114 * indicate whether the input components to this processor in the FS will have known values.
115 * In inout the validFlags member is a bitfield of GrColorComponentFlags. The isSingleComponent
116 * member indicates whether the input will be 1 or 4 bytes. The function updates the members of
117 * inout to indicate known values of its output. A component of the color member only has
118 * meaning if the corresponding bit in validFlags is set.
119 */
bsalomonc21b09e2015-08-28 18:46:56 -0700120 void computeInvariantOutput(GrInvariantOutput* inout) const {
121 this->onComputeInvariantOutput(inout);
122 }
joshualitt56995b52014-12-11 15:44:02 -0800123
bsalomona624bf32016-09-20 09:12:47 -0700124 /**
125 * Pre-order traversal of a FP hierarchy, or of the forest of FPs in a GrPipeline. In the latter
126 * case the tree rooted at each FP in the GrPipeline is visited successively.
bsalomonb58a2b42016-09-26 06:55:02 -0700127 */
bsalomona624bf32016-09-20 09:12:47 -0700128 class Iter : public SkNoncopyable {
129 public:
130 explicit Iter(const GrFragmentProcessor* fp) { fFPStack.push_back(fp); }
131 explicit Iter(const GrPipeline& pipeline);
132 const GrFragmentProcessor* next();
133
134 private:
135 SkSTArray<4, const GrFragmentProcessor*, true> fFPStack;
136 };
137
138 /**
bsalomonb58a2b42016-09-26 06:55:02 -0700139 * Iterates over all the Ts owned by a GrFragmentProcessor and its children or over all the Ts
140 * owned by the forest of GrFragmentProcessors in a GrPipeline. FPs are visited in the same
141 * order as Iter and each of an FP's Ts are visited in order.
bsalomona624bf32016-09-20 09:12:47 -0700142 */
bsalomonb58a2b42016-09-26 06:55:02 -0700143 template <typename T, typename BASE,
144 int (BASE::*COUNT)() const,
145 const T& (BASE::*GET)(int) const>
146 class FPItemIter : public SkNoncopyable {
bsalomona624bf32016-09-20 09:12:47 -0700147 public:
bsalomonb58a2b42016-09-26 06:55:02 -0700148 explicit FPItemIter(const GrFragmentProcessor* fp)
149 : fCurrFP(nullptr)
150 , fCTIdx(0)
151 , fFPIter(fp) {
152 fCurrFP = fFPIter.next();
153 }
154 explicit FPItemIter(const GrPipeline& pipeline)
bsalomona624bf32016-09-20 09:12:47 -0700155 : fCurrFP(nullptr)
156 , fCTIdx(0)
157 , fFPIter(pipeline) {
158 fCurrFP = fFPIter.next();
159 }
bsalomonb58a2b42016-09-26 06:55:02 -0700160
161 const T* next() {
162 if (!fCurrFP) {
163 return nullptr;
164 }
165 while (fCTIdx == (fCurrFP->*COUNT)()) {
166 fCTIdx = 0;
167 fCurrFP = fFPIter.next();
168 if (!fCurrFP) {
169 return nullptr;
170 }
171 }
172 return &(fCurrFP->*GET)(fCTIdx++);
173 }
bsalomona624bf32016-09-20 09:12:47 -0700174
175 private:
176 const GrFragmentProcessor* fCurrFP;
177 int fCTIdx;
178 GrFragmentProcessor::Iter fFPIter;
179 };
180
bsalomonb58a2b42016-09-26 06:55:02 -0700181 using CoordTransformIter = FPItemIter<GrCoordTransform,
182 GrFragmentProcessor,
183 &GrFragmentProcessor::numCoordTransforms,
184 &GrFragmentProcessor::coordTransform>;
185
186 using TextureAccessIter = FPItemIter<GrTextureAccess,
187 GrProcessor,
188 &GrProcessor::numTextures,
189 &GrProcessor::textureAccess>;
190
bsalomon6251d172014-10-15 10:50:36 -0700191protected:
wangyix93ab2542015-08-19 08:23:12 -0700192 void addTextureAccess(const GrTextureAccess* textureAccess) override;
cdalton74b8d322016-04-11 14:47:28 -0700193 void addBufferAccess(const GrBufferAccess*) override;
wangyix93ab2542015-08-19 08:23:12 -0700194
bsalomon6251d172014-10-15 10:50:36 -0700195 /**
196 * Fragment Processor subclasses call this from their constructor to register coordinate
bsalomonde258cd2014-10-15 19:06:21 -0700197 * transformations. Coord transforms provide a mechanism for a processor to receive coordinates
198 * in their FS code. The matrix expresses a transformation from local space. For a given
199 * fragment the matrix will be applied to the local coordinate that maps to the fragment.
200 *
201 * When the transformation has perspective, the transformed coordinates will have
mtklein790d74f2015-08-19 11:05:39 -0700202 * 3 components. Otherwise they'll have 2.
bsalomonde258cd2014-10-15 19:06:21 -0700203 *
204 * This must only be called from the constructor because GrProcessors are immutable. The
205 * processor subclass manages the lifetime of the transformations (this function only stores a
mtklein790d74f2015-08-19 11:05:39 -0700206 * pointer). The GrCoordTransform is typically a member field of the GrProcessor subclass.
bsalomonde258cd2014-10-15 19:06:21 -0700207 *
208 * A processor subclass that has multiple methods of construction should always add its coord
209 * transforms in a consistent order. The non-virtual implementation of isEqual() automatically
210 * compares transforms and will assume they line up across the two processor instances.
bsalomon6251d172014-10-15 10:50:36 -0700211 */
212 void addCoordTransform(const GrCoordTransform*);
213
214 /**
wangyix58d890b2015-08-12 09:40:47 -0700215 * FragmentProcessor subclasses call this from their constructor to register any child
wangyix93ab2542015-08-19 08:23:12 -0700216 * FragmentProcessors they have. This must be called AFTER all texture accesses and coord
217 * transforms have been added.
wangyix4b3050b2015-08-04 07:59:37 -0700218 * This is for processors whose shader code will be composed of nested processors whose output
219 * colors will be combined somehow to produce its output color. Registering these child
wangyix58d890b2015-08-12 09:40:47 -0700220 * processors will allow the ProgramBuilder to automatically handle their transformed coords and
221 * texture accesses and mangle their uniform and output color names.
wangyix4b3050b2015-08-04 07:59:37 -0700222 */
bungeman06ca8ec2016-06-09 08:01:03 -0700223 int registerChildProcessor(sk_sp<GrFragmentProcessor> child);
wangyix4b3050b2015-08-04 07:59:37 -0700224
225 /**
joshualitt56995b52014-12-11 15:44:02 -0800226 * Subclass implements this to support getConstantColorComponents(...).
wangyix54017d72015-08-18 07:39:33 -0700227 *
228 * Note: it's up to the subclass implementation to do any recursive call to compute the child
229 * procs' output invariants; computeInvariantOutput will not be recursive.
joshualitt56995b52014-12-11 15:44:02 -0800230 */
231 virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const = 0;
232
dvonbeck9b03e7b2016-08-01 11:01:56 -0700233 /* Sub-classes should set this to true in their constructors if they need access to a distance
234 * vector field to the nearest edge
235 */
236 bool fUsesDistanceVectorField;
237
bsalomon6251d172014-10-15 10:50:36 -0700238private:
bsalomon42048002015-08-27 16:43:48 -0700239 void notifyRefCntIsZero() const final;
240
wangyixb1daa862015-08-18 11:29:31 -0700241 /** Returns a new instance of the appropriate *GL* implementation class
242 for the given GrFragmentProcessor; caller is responsible for deleting
243 the object. */
egdaniel57d3b032015-11-13 11:57:27 -0800244 virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const = 0;
wangyixb1daa862015-08-18 11:29:31 -0700245
wangyix4b3050b2015-08-04 07:59:37 -0700246 /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */
egdaniel57d3b032015-11-13 11:57:27 -0800247 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
248 GrProcessorKeyBuilder* b) const = 0;
wangyix4b3050b2015-08-04 07:59:37 -0700249
bsalomonde258cd2014-10-15 19:06:21 -0700250 /**
251 * Subclass implements this to support isEqual(). It will only be called if it is known that
252 * the two processors are of the same subclass (i.e. they return the same object from
253 * getFactory()). The processor subclass should not compare its coord transforms as that will
254 * be performed automatically in the non-virtual isEqual().
255 */
256 virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
257
258 bool hasSameTransforms(const GrFragmentProcessor&) const;
bsalomon6251d172014-10-15 10:50:36 -0700259
bungeman06ca8ec2016-06-09 08:01:03 -0700260 bool fUsesLocalCoords;
wangyix58d890b2015-08-12 09:40:47 -0700261
bsalomona624bf32016-09-20 09:12:47 -0700262 SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms;
263
wangyix58d890b2015-08-12 09:40:47 -0700264 /**
bungeman06ca8ec2016-06-09 08:01:03 -0700265 * This is not SkSTArray<1, sk_sp<GrFragmentProcessor>> because this class holds strong
266 * references until notifyRefCntIsZero and then it holds pending executions.
267 */
268 SkSTArray<1, GrFragmentProcessor*, true> fChildProcessors;
bsalomon6251d172014-10-15 10:50:36 -0700269
270 typedef GrProcessor INHERITED;
271};
272
bsalomon6251d172014-10-15 10:50:36 -0700273#endif