blob: c95c5e59567ca86d25c597f03a400ce78d835d63 [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;
egdaniel64c47282015-11-13 06:54:19 -080014class GrGLSLFragmentProcessor;
bsalomonc21b09e2015-08-28 18:46:56 -070015class GrInvariantOutput;
bsalomona624bf32016-09-20 09:12:47 -070016class GrPipeline;
joshualitteb2a6762014-12-04 11:35:33 -080017class GrProcessorKeyBuilder;
Brian Salomon94efbf52016-11-29 13:43:05 -050018class GrShaderCaps;
Brian Osmance425512017-03-22 14:37:50 -040019class GrSwizzle;
bsalomon6251d172014-10-15 10:50:36 -070020
21/** Provides custom fragment shader code. Fragment processors receive an input color (vec4f) and
22 produce an output color. They may reference textures and uniforms. They may use
23 GrCoordTransforms to receive a transformation of the local coordinates that map from local space
24 to the fragment being processed.
25 */
26class GrFragmentProcessor : public GrProcessor {
27public:
bsalomon87ba62e2015-09-22 06:41:59 -070028 /**
29 * In many instances (e.g. SkShader::asFragmentProcessor() implementations) it is desirable to
30 * only consider the input color's alpha. However, there is a competing desire to have reusable
31 * GrFragmentProcessor subclasses that can be used in other scenarios where the entire input
32 * color is considered. This function exists to filter the input color and pass it to a FP. It
33 * does so by returning a parent FP that multiplies the passed in FPs output by the parent's
34 * input alpha. The passed in FP will not receive an input color.
35 */
bungeman06ca8ec2016-06-09 08:01:03 -070036 static sk_sp<GrFragmentProcessor> MulOutputByInputAlpha(sk_sp<GrFragmentProcessor>);
bsalomonf1b7a1d2015-09-28 06:26:28 -070037
38 /**
Brian Salomon22af73f2017-01-26 11:25:12 -050039 * This assumes that the input color to the returned processor will be unpremul and that the
40 * passed processor (which becomes the returned processor's child) produces a premul output.
41 * The result of the returned processor is a premul of its input color modulated by the child
42 * processor's premul output.
bsalomonf1b7a1d2015-09-28 06:26:28 -070043 */
Brian Salomon22af73f2017-01-26 11:25:12 -050044 static sk_sp<GrFragmentProcessor> MakeInputPremulAndMulByOutput(sk_sp<GrFragmentProcessor>);
bsalomonf1b7a1d2015-09-28 06:26:28 -070045
46 /**
bsalomone25eea42015-09-29 06:38:55 -070047 * Returns a parent fragment processor that adopts the passed fragment processor as a child.
48 * The parent will ignore its input color and instead feed the passed in color as input to the
49 * child.
bsalomonf1b7a1d2015-09-28 06:26:28 -070050 */
brianosman4cea3b92016-09-08 09:33:50 -070051 static sk_sp<GrFragmentProcessor> OverrideInput(sk_sp<GrFragmentProcessor>, GrColor4f);
bsalomon87ba62e2015-09-22 06:41:59 -070052
bsalomone25eea42015-09-29 06:38:55 -070053 /**
dvonbeckc526da92016-07-20 11:20:30 -070054 * Returns a fragment processor that premuls the input before calling the passed in fragment
55 * processor.
56 */
57 static sk_sp<GrFragmentProcessor> PremulInput(sk_sp<GrFragmentProcessor>);
58
59 /**
Brian Osmande1a6052017-03-22 10:57:00 -040060 * Returns a fragment processor that calls the passed in fragment processor, and then premuls
61 * the output.
62 */
63 static sk_sp<GrFragmentProcessor> PremulOutput(sk_sp<GrFragmentProcessor>);
64
65 /**
66 * Returns a fragment processor that calls the passed in fragment processor, and then unpremuls
67 * the output.
68 */
69 static sk_sp<GrFragmentProcessor> UnpremulOutput(sk_sp<GrFragmentProcessor>);
70
71 /**
Brian Osmance425512017-03-22 14:37:50 -040072 * Returns a fragment processor that calls the passed in fragment processor, and then swizzles
73 * the output.
74 */
75 static sk_sp<GrFragmentProcessor> SwizzleOutput(sk_sp<GrFragmentProcessor>, const GrSwizzle&);
76
77 /**
bsalomone25eea42015-09-29 06:38:55 -070078 * Returns a fragment processor that runs the passed in array of fragment processors in a
79 * series. The original input is passed to the first, the first's output is passed to the
80 * second, etc. The output of the returned processor is the output of the last processor of the
81 * series.
bungeman06ca8ec2016-06-09 08:01:03 -070082 *
83 * The array elements with be moved.
bsalomone25eea42015-09-29 06:38:55 -070084 */
bungeman06ca8ec2016-06-09 08:01:03 -070085 static sk_sp<GrFragmentProcessor> RunInSeries(sk_sp<GrFragmentProcessor>*, int cnt);
bsalomone25eea42015-09-29 06:38:55 -070086
bsalomonac856c92015-08-27 06:30:17 -070087 ~GrFragmentProcessor() override;
88
egdaniel57d3b032015-11-13 11:57:27 -080089 GrGLSLFragmentProcessor* createGLSLInstance() const;
joshualitteb2a6762014-12-04 11:35:33 -080090
Brian Salomon94efbf52016-11-29 13:43:05 -050091 void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
egdaniel57d3b032015-11-13 11:57:27 -080092 this->onGetGLSLProcessorKey(caps, b);
wangyix4b3050b2015-08-04 07:59:37 -070093 for (int i = 0; i < fChildProcessors.count(); ++i) {
egdaniel57d3b032015-11-13 11:57:27 -080094 fChildProcessors[i]->getGLSLProcessorKey(caps, b);
wangyix4b3050b2015-08-04 07:59:37 -070095 }
96 }
97
bsalomona624bf32016-09-20 09:12:47 -070098 int numCoordTransforms() const { return fCoordTransforms.count(); }
bsalomon6251d172014-10-15 10:50:36 -070099
100 /** Returns the coordinate transformation at index. index must be valid according to
101 numTransforms(). */
102 const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
103
joshualittabb52a12015-01-13 15:02:10 -0800104 const SkTArray<const GrCoordTransform*, true>& coordTransforms() const {
105 return fCoordTransforms;
106 }
107
wangyix4b3050b2015-08-04 07:59:37 -0700108 int numChildProcessors() const { return fChildProcessors.count(); }
109
bsalomonac856c92015-08-27 06:30:17 -0700110 const GrFragmentProcessor& childProcessor(int index) const { return *fChildProcessors[index]; }
wangyix4b3050b2015-08-04 07:59:37 -0700111
joshualitt290c09b2014-12-19 13:45:20 -0800112 /** Do any of the coordtransforms for this processor require local coords? */
Brian Salomon587e08f2017-01-27 10:59:27 -0500113 bool usesLocalCoords() const { return SkToBool(fFlags & kUsesLocalCoords_Flag); }
joshualitt290c09b2014-12-19 13:45:20 -0800114
dvonbeck9b03e7b2016-08-01 11:01:56 -0700115 /** Does this FP need a vector to the nearest edge? */
Brian Salomon587e08f2017-01-27 10:59:27 -0500116 bool usesDistanceVectorField() const {
117 return SkToBool(fFlags & kUsesDistanceVectorField_Flag);
118 }
119
120 /**
Brian Salomonf3b995b2017-02-15 10:22:23 -0500121 * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
122 * output under the following scenario:
123 * * all the color fragment processors report true to this query,
124 * * all the coverage fragment processors report true to this query,
125 * * the blend mode arithmetic allows for it it.
126 * To be compatible a fragment processor's output must be a modulation of its input color or
127 * alpha with a computed premultiplied color or alpha that is in 0..1 range. The computed color
128 * or alpha that is modulated against the input cannot depend on the input's alpha. The computed
129 * value cannot depend on the input's color channels unless it unpremultiplies the input color
130 * channels by the input alpha.
Brian Salomon587e08f2017-01-27 10:59:27 -0500131 */
Brian Salomonf3b995b2017-02-15 10:22:23 -0500132 bool compatibleWithCoverageAsAlpha() const {
133 return SkToBool(fFlags & kCompatibleWithCoverageAsAlpha_OptimizationFlag);
134 }
Brian Salomon587e08f2017-01-27 10:59:27 -0500135
136 /**
137 * If this is true then all opaque input colors to the processor produce opaque output colors.
138 */
139 bool preservesOpaqueInput() const {
140 return SkToBool(fFlags & kPreservesOpaqueInput_OptimizationFlag);
141 }
142
143 /**
144 * Tests whether given a constant input color the processor produces a constant output color
145 * (for all fragments). If true outputColor will contain the constant color produces for
146 * inputColor.
147 */
148 bool hasConstantOutputForConstantInput(GrColor4f inputColor, GrColor4f* outputColor) const {
149 if (fFlags & kConstantOutputForConstantInput_OptimizationFlag) {
150 *outputColor = this->constantOutputForConstantInput(inputColor);
151 return true;
152 }
153 return false;
154 }
155 bool hasConstantOutputForConstantInput() const {
156 return SkToBool(fFlags & kConstantOutputForConstantInput_OptimizationFlag);
157 }
dvonbeck9b03e7b2016-08-01 11:01:56 -0700158
joshualitteb2a6762014-12-04 11:35:33 -0800159 /** Returns true if this and other processor conservatively draw identically. It can only return
160 true when the two processor are of the same subclass (i.e. they return the same object from
bsalomon6251d172014-10-15 10:50:36 -0700161 from getFactory()).
162
joshualitteb2a6762014-12-04 11:35:33 -0800163 A return value of true from isEqual() should not be used to test whether the processor would
egdaniel57d3b032015-11-13 11:57:27 -0800164 generate the same shader code. To test for identical code generation use getGLSLProcessorKey
165 */
bsalomon7312ff82016-09-12 08:55:38 -0700166 bool isEqual(const GrFragmentProcessor& that) const;
bsalomon6251d172014-10-15 10:50:36 -0700167
joshualitt56995b52014-12-11 15:44:02 -0800168 /**
bsalomona624bf32016-09-20 09:12:47 -0700169 * Pre-order traversal of a FP hierarchy, or of the forest of FPs in a GrPipeline. In the latter
170 * case the tree rooted at each FP in the GrPipeline is visited successively.
bsalomonb58a2b42016-09-26 06:55:02 -0700171 */
bsalomona624bf32016-09-20 09:12:47 -0700172 class Iter : public SkNoncopyable {
173 public:
174 explicit Iter(const GrFragmentProcessor* fp) { fFPStack.push_back(fp); }
175 explicit Iter(const GrPipeline& pipeline);
176 const GrFragmentProcessor* next();
177
178 private:
179 SkSTArray<4, const GrFragmentProcessor*, true> fFPStack;
180 };
181
182 /**
bsalomonb58a2b42016-09-26 06:55:02 -0700183 * Iterates over all the Ts owned by a GrFragmentProcessor and its children or over all the Ts
184 * owned by the forest of GrFragmentProcessors in a GrPipeline. FPs are visited in the same
185 * order as Iter and each of an FP's Ts are visited in order.
bsalomona624bf32016-09-20 09:12:47 -0700186 */
bsalomonb58a2b42016-09-26 06:55:02 -0700187 template <typename T, typename BASE,
188 int (BASE::*COUNT)() const,
189 const T& (BASE::*GET)(int) const>
190 class FPItemIter : public SkNoncopyable {
bsalomona624bf32016-09-20 09:12:47 -0700191 public:
bsalomonb58a2b42016-09-26 06:55:02 -0700192 explicit FPItemIter(const GrFragmentProcessor* fp)
193 : fCurrFP(nullptr)
194 , fCTIdx(0)
195 , fFPIter(fp) {
196 fCurrFP = fFPIter.next();
197 }
198 explicit FPItemIter(const GrPipeline& pipeline)
bsalomona624bf32016-09-20 09:12:47 -0700199 : fCurrFP(nullptr)
200 , fCTIdx(0)
201 , fFPIter(pipeline) {
202 fCurrFP = fFPIter.next();
203 }
bsalomonb58a2b42016-09-26 06:55:02 -0700204
205 const T* next() {
206 if (!fCurrFP) {
207 return nullptr;
208 }
209 while (fCTIdx == (fCurrFP->*COUNT)()) {
210 fCTIdx = 0;
211 fCurrFP = fFPIter.next();
212 if (!fCurrFP) {
213 return nullptr;
214 }
215 }
216 return &(fCurrFP->*GET)(fCTIdx++);
217 }
bsalomona624bf32016-09-20 09:12:47 -0700218
219 private:
220 const GrFragmentProcessor* fCurrFP;
221 int fCTIdx;
222 GrFragmentProcessor::Iter fFPIter;
223 };
224
bsalomonb58a2b42016-09-26 06:55:02 -0700225 using CoordTransformIter = FPItemIter<GrCoordTransform,
226 GrFragmentProcessor,
227 &GrFragmentProcessor::numCoordTransforms,
228 &GrFragmentProcessor::coordTransform>;
229
Brian Salomon0bbecb22016-11-17 11:38:22 -0500230 using TextureAccessIter = FPItemIter<TextureSampler,
bsalomonb58a2b42016-09-26 06:55:02 -0700231 GrProcessor,
Brian Salomon0bbecb22016-11-17 11:38:22 -0500232 &GrProcessor::numTextureSamplers,
233 &GrProcessor::textureSampler>;
bsalomonb58a2b42016-09-26 06:55:02 -0700234
bsalomon6251d172014-10-15 10:50:36 -0700235protected:
Brian Salomon587e08f2017-01-27 10:59:27 -0500236 enum OptimizationFlags : uint32_t {
237 kNone_OptimizationFlags,
Brian Salomonf3b995b2017-02-15 10:22:23 -0500238 kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1,
Brian Salomon587e08f2017-01-27 10:59:27 -0500239 kPreservesOpaqueInput_OptimizationFlag = 0x2,
240 kConstantOutputForConstantInput_OptimizationFlag = 0x4,
Brian Salomonf3b995b2017-02-15 10:22:23 -0500241 kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag |
Brian Salomon587e08f2017-01-27 10:59:27 -0500242 kPreservesOpaqueInput_OptimizationFlag |
243 kConstantOutputForConstantInput_OptimizationFlag
244 };
245 GR_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)
246
247 GrFragmentProcessor(OptimizationFlags optimizationFlags) : fFlags(optimizationFlags) {
248 SkASSERT((fFlags & ~kAll_OptimizationFlags) == 0);
249 }
250
251 OptimizationFlags optimizationFlags() const {
252 return static_cast<OptimizationFlags>(kAll_OptimizationFlags & fFlags);
253 }
254
255 /**
256 * This allows one subclass to access another subclass's implementation of
257 * constantOutputForConstantInput. It must only be called when
258 * hasConstantOutputForConstantInput() is known to be true.
259 */
260 static GrColor4f ConstantOutputForConstantInput(const GrFragmentProcessor& fp,
261 GrColor4f input) {
262 SkASSERT(fp.hasConstantOutputForConstantInput());
263 return fp.constantOutputForConstantInput(input);
264 }
265
bsalomon6251d172014-10-15 10:50:36 -0700266 /**
267 * Fragment Processor subclasses call this from their constructor to register coordinate
bsalomonde258cd2014-10-15 19:06:21 -0700268 * transformations. Coord transforms provide a mechanism for a processor to receive coordinates
269 * in their FS code. The matrix expresses a transformation from local space. For a given
270 * fragment the matrix will be applied to the local coordinate that maps to the fragment.
271 *
272 * When the transformation has perspective, the transformed coordinates will have
mtklein790d74f2015-08-19 11:05:39 -0700273 * 3 components. Otherwise they'll have 2.
bsalomonde258cd2014-10-15 19:06:21 -0700274 *
275 * This must only be called from the constructor because GrProcessors are immutable. The
276 * processor subclass manages the lifetime of the transformations (this function only stores a
mtklein790d74f2015-08-19 11:05:39 -0700277 * pointer). The GrCoordTransform is typically a member field of the GrProcessor subclass.
bsalomonde258cd2014-10-15 19:06:21 -0700278 *
279 * A processor subclass that has multiple methods of construction should always add its coord
280 * transforms in a consistent order. The non-virtual implementation of isEqual() automatically
281 * compares transforms and will assume they line up across the two processor instances.
bsalomon6251d172014-10-15 10:50:36 -0700282 */
283 void addCoordTransform(const GrCoordTransform*);
284
285 /**
wangyix58d890b2015-08-12 09:40:47 -0700286 * FragmentProcessor subclasses call this from their constructor to register any child
wangyix93ab2542015-08-19 08:23:12 -0700287 * FragmentProcessors they have. This must be called AFTER all texture accesses and coord
288 * transforms have been added.
wangyix4b3050b2015-08-04 07:59:37 -0700289 * This is for processors whose shader code will be composed of nested processors whose output
290 * colors will be combined somehow to produce its output color. Registering these child
wangyix58d890b2015-08-12 09:40:47 -0700291 * processors will allow the ProgramBuilder to automatically handle their transformed coords and
292 * texture accesses and mangle their uniform and output color names.
wangyix4b3050b2015-08-04 07:59:37 -0700293 */
bungeman06ca8ec2016-06-09 08:01:03 -0700294 int registerChildProcessor(sk_sp<GrFragmentProcessor> child);
wangyix4b3050b2015-08-04 07:59:37 -0700295
296 /**
Brian Salomon587e08f2017-01-27 10:59:27 -0500297 * Sub-classes should call this in their constructors if they need access to a distance
dvonbeck9b03e7b2016-08-01 11:01:56 -0700298 * vector field to the nearest edge
299 */
Brian Salomon587e08f2017-01-27 10:59:27 -0500300 void setWillUseDistanceVectorField() { fFlags |= kUsesDistanceVectorField_Flag; }
dvonbeck9b03e7b2016-08-01 11:01:56 -0700301
bsalomon6251d172014-10-15 10:50:36 -0700302private:
bsalomon42048002015-08-27 16:43:48 -0700303 void notifyRefCntIsZero() const final;
304
Brian Salomon587e08f2017-01-27 10:59:27 -0500305 virtual GrColor4f constantOutputForConstantInput(GrColor4f /* inputColor */) const {
306 SkFAIL("Subclass must override this if advertising this optimization.");
307 return GrColor4f::TransparentBlack();
308 }
309
wangyixb1daa862015-08-18 11:29:31 -0700310 /** Returns a new instance of the appropriate *GL* implementation class
311 for the given GrFragmentProcessor; caller is responsible for deleting
312 the object. */
egdaniel57d3b032015-11-13 11:57:27 -0800313 virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const = 0;
wangyixb1daa862015-08-18 11:29:31 -0700314
wangyix4b3050b2015-08-04 07:59:37 -0700315 /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */
Brian Salomon94efbf52016-11-29 13:43:05 -0500316 virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
wangyix4b3050b2015-08-04 07:59:37 -0700317
bsalomonde258cd2014-10-15 19:06:21 -0700318 /**
319 * Subclass implements this to support isEqual(). It will only be called if it is known that
320 * the two processors are of the same subclass (i.e. they return the same object from
321 * getFactory()). The processor subclass should not compare its coord transforms as that will
322 * be performed automatically in the non-virtual isEqual().
323 */
324 virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
325
326 bool hasSameTransforms(const GrFragmentProcessor&) const;
bsalomon6251d172014-10-15 10:50:36 -0700327
Brian Salomon587e08f2017-01-27 10:59:27 -0500328 enum PrivateFlags {
329 kFirstPrivateFlag = kAll_OptimizationFlags + 1,
330 kUsesLocalCoords_Flag = kFirstPrivateFlag,
331 kUsesDistanceVectorField_Flag = kFirstPrivateFlag << 1,
332 };
333
334 mutable uint32_t fFlags = 0;
wangyix58d890b2015-08-12 09:40:47 -0700335
bsalomona624bf32016-09-20 09:12:47 -0700336 SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms;
337
wangyix58d890b2015-08-12 09:40:47 -0700338 /**
bungeman06ca8ec2016-06-09 08:01:03 -0700339 * This is not SkSTArray<1, sk_sp<GrFragmentProcessor>> because this class holds strong
340 * references until notifyRefCntIsZero and then it holds pending executions.
341 */
Brian Salomon587e08f2017-01-27 10:59:27 -0500342 SkSTArray<1, GrFragmentProcessor*, true> fChildProcessors;
bsalomon6251d172014-10-15 10:50:36 -0700343
344 typedef GrProcessor INHERITED;
345};
346
Brian Salomon587e08f2017-01-27 10:59:27 -0500347GR_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)
348
bsalomon6251d172014-10-15 10:50:36 -0700349#endif