blob: 0784031d30dd5d1807594caf6103a4d4468faabb [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
Ethan Nicholas5af9ea32017-07-28 15:19:46 -040021/** Provides custom fragment shader code. Fragment processors receive an input color (float4) and
bsalomon6251d172014-10-15 10:50:36 -070022 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 */
Brian Salomond61c9d92017-04-10 10:54:25 -040026class GrFragmentProcessor : public GrResourceIOProcessor, public GrProgramElement {
bsalomon6251d172014-10-15 10:50:36 -070027public:
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
Brian Salomon0e05a822017-07-25 09:43:22 -040089 /**
90 * Makes a copy of this fragment processor that draws equivalently to the original.
Brian Salomon96271cd2017-07-31 16:27:23 -040091 * If the processor has child processors they are cloned as well.
Brian Salomon0e05a822017-07-25 09:43:22 -040092 */
Brian Salomon96271cd2017-07-31 16:27:23 -040093 virtual sk_sp<GrFragmentProcessor> clone() const = 0;
Brian Salomon0e05a822017-07-25 09:43:22 -040094
egdaniel57d3b032015-11-13 11:57:27 -080095 GrGLSLFragmentProcessor* createGLSLInstance() const;
joshualitteb2a6762014-12-04 11:35:33 -080096
Brian Salomon94efbf52016-11-29 13:43:05 -050097 void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
egdaniel57d3b032015-11-13 11:57:27 -080098 this->onGetGLSLProcessorKey(caps, b);
wangyix4b3050b2015-08-04 07:59:37 -070099 for (int i = 0; i < fChildProcessors.count(); ++i) {
egdaniel57d3b032015-11-13 11:57:27 -0800100 fChildProcessors[i]->getGLSLProcessorKey(caps, b);
wangyix4b3050b2015-08-04 07:59:37 -0700101 }
102 }
103
bsalomona624bf32016-09-20 09:12:47 -0700104 int numCoordTransforms() const { return fCoordTransforms.count(); }
bsalomon6251d172014-10-15 10:50:36 -0700105
106 /** Returns the coordinate transformation at index. index must be valid according to
107 numTransforms(). */
108 const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
109
joshualittabb52a12015-01-13 15:02:10 -0800110 const SkTArray<const GrCoordTransform*, true>& coordTransforms() const {
111 return fCoordTransforms;
112 }
113
wangyix4b3050b2015-08-04 07:59:37 -0700114 int numChildProcessors() const { return fChildProcessors.count(); }
115
bsalomonac856c92015-08-27 06:30:17 -0700116 const GrFragmentProcessor& childProcessor(int index) const { return *fChildProcessors[index]; }
wangyix4b3050b2015-08-04 07:59:37 -0700117
Robert Phillips9bee2e52017-05-29 12:37:20 -0400118 bool instantiate(GrResourceProvider*) const;
119
joshualitt290c09b2014-12-19 13:45:20 -0800120 /** Do any of the coordtransforms for this processor require local coords? */
Brian Salomon587e08f2017-01-27 10:59:27 -0500121 bool usesLocalCoords() const { return SkToBool(fFlags & kUsesLocalCoords_Flag); }
joshualitt290c09b2014-12-19 13:45:20 -0800122
Brian Salomon587e08f2017-01-27 10:59:27 -0500123 /**
Brian Salomonf3b995b2017-02-15 10:22:23 -0500124 * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
125 * output under the following scenario:
126 * * all the color fragment processors report true to this query,
127 * * all the coverage fragment processors report true to this query,
128 * * the blend mode arithmetic allows for it it.
129 * To be compatible a fragment processor's output must be a modulation of its input color or
130 * alpha with a computed premultiplied color or alpha that is in 0..1 range. The computed color
131 * or alpha that is modulated against the input cannot depend on the input's alpha. The computed
132 * value cannot depend on the input's color channels unless it unpremultiplies the input color
133 * channels by the input alpha.
Brian Salomon587e08f2017-01-27 10:59:27 -0500134 */
Brian Salomonf3b995b2017-02-15 10:22:23 -0500135 bool compatibleWithCoverageAsAlpha() const {
136 return SkToBool(fFlags & kCompatibleWithCoverageAsAlpha_OptimizationFlag);
137 }
Brian Salomon587e08f2017-01-27 10:59:27 -0500138
139 /**
140 * If this is true then all opaque input colors to the processor produce opaque output colors.
141 */
142 bool preservesOpaqueInput() const {
143 return SkToBool(fFlags & kPreservesOpaqueInput_OptimizationFlag);
144 }
145
146 /**
147 * Tests whether given a constant input color the processor produces a constant output color
148 * (for all fragments). If true outputColor will contain the constant color produces for
149 * inputColor.
150 */
151 bool hasConstantOutputForConstantInput(GrColor4f inputColor, GrColor4f* outputColor) const {
152 if (fFlags & kConstantOutputForConstantInput_OptimizationFlag) {
153 *outputColor = this->constantOutputForConstantInput(inputColor);
154 return true;
155 }
156 return false;
157 }
158 bool hasConstantOutputForConstantInput() const {
159 return SkToBool(fFlags & kConstantOutputForConstantInput_OptimizationFlag);
160 }
dvonbeck9b03e7b2016-08-01 11:01:56 -0700161
joshualitteb2a6762014-12-04 11:35:33 -0800162 /** Returns true if this and other processor conservatively draw identically. It can only return
163 true when the two processor are of the same subclass (i.e. they return the same object from
bsalomon6251d172014-10-15 10:50:36 -0700164 from getFactory()).
165
joshualitteb2a6762014-12-04 11:35:33 -0800166 A return value of true from isEqual() should not be used to test whether the processor would
egdaniel57d3b032015-11-13 11:57:27 -0800167 generate the same shader code. To test for identical code generation use getGLSLProcessorKey
168 */
bsalomon7312ff82016-09-12 08:55:38 -0700169 bool isEqual(const GrFragmentProcessor& that) const;
bsalomon6251d172014-10-15 10:50:36 -0700170
joshualitt56995b52014-12-11 15:44:02 -0800171 /**
bsalomona624bf32016-09-20 09:12:47 -0700172 * Pre-order traversal of a FP hierarchy, or of the forest of FPs in a GrPipeline. In the latter
173 * case the tree rooted at each FP in the GrPipeline is visited successively.
bsalomonb58a2b42016-09-26 06:55:02 -0700174 */
bsalomona624bf32016-09-20 09:12:47 -0700175 class Iter : public SkNoncopyable {
176 public:
177 explicit Iter(const GrFragmentProcessor* fp) { fFPStack.push_back(fp); }
178 explicit Iter(const GrPipeline& pipeline);
179 const GrFragmentProcessor* next();
180
181 private:
182 SkSTArray<4, const GrFragmentProcessor*, true> fFPStack;
183 };
184
185 /**
bsalomonb58a2b42016-09-26 06:55:02 -0700186 * Iterates over all the Ts owned by a GrFragmentProcessor and its children or over all the Ts
187 * owned by the forest of GrFragmentProcessors in a GrPipeline. FPs are visited in the same
188 * order as Iter and each of an FP's Ts are visited in order.
bsalomona624bf32016-09-20 09:12:47 -0700189 */
bsalomonb58a2b42016-09-26 06:55:02 -0700190 template <typename T, typename BASE,
191 int (BASE::*COUNT)() const,
192 const T& (BASE::*GET)(int) const>
193 class FPItemIter : public SkNoncopyable {
bsalomona624bf32016-09-20 09:12:47 -0700194 public:
bsalomonb58a2b42016-09-26 06:55:02 -0700195 explicit FPItemIter(const GrFragmentProcessor* fp)
196 : fCurrFP(nullptr)
197 , fCTIdx(0)
198 , fFPIter(fp) {
199 fCurrFP = fFPIter.next();
200 }
201 explicit FPItemIter(const GrPipeline& pipeline)
bsalomona624bf32016-09-20 09:12:47 -0700202 : fCurrFP(nullptr)
203 , fCTIdx(0)
204 , fFPIter(pipeline) {
205 fCurrFP = fFPIter.next();
206 }
bsalomonb58a2b42016-09-26 06:55:02 -0700207
208 const T* next() {
209 if (!fCurrFP) {
210 return nullptr;
211 }
212 while (fCTIdx == (fCurrFP->*COUNT)()) {
213 fCTIdx = 0;
214 fCurrFP = fFPIter.next();
215 if (!fCurrFP) {
216 return nullptr;
217 }
218 }
219 return &(fCurrFP->*GET)(fCTIdx++);
220 }
bsalomona624bf32016-09-20 09:12:47 -0700221
222 private:
223 const GrFragmentProcessor* fCurrFP;
224 int fCTIdx;
225 GrFragmentProcessor::Iter fFPIter;
226 };
227
bsalomonb58a2b42016-09-26 06:55:02 -0700228 using CoordTransformIter = FPItemIter<GrCoordTransform,
229 GrFragmentProcessor,
230 &GrFragmentProcessor::numCoordTransforms,
231 &GrFragmentProcessor::coordTransform>;
232
Brian Salomon0bbecb22016-11-17 11:38:22 -0500233 using TextureAccessIter = FPItemIter<TextureSampler,
Brian Salomonab015ef2017-04-04 10:15:51 -0400234 GrResourceIOProcessor,
235 &GrResourceIOProcessor::numTextureSamplers,
236 &GrResourceIOProcessor::textureSampler>;
bsalomonb58a2b42016-09-26 06:55:02 -0700237
bsalomon6251d172014-10-15 10:50:36 -0700238protected:
Brian Salomon587e08f2017-01-27 10:59:27 -0500239 enum OptimizationFlags : uint32_t {
240 kNone_OptimizationFlags,
Brian Salomonf3b995b2017-02-15 10:22:23 -0500241 kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1,
Brian Salomon587e08f2017-01-27 10:59:27 -0500242 kPreservesOpaqueInput_OptimizationFlag = 0x2,
243 kConstantOutputForConstantInput_OptimizationFlag = 0x4,
Brian Salomonf3b995b2017-02-15 10:22:23 -0500244 kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag |
Brian Salomon587e08f2017-01-27 10:59:27 -0500245 kPreservesOpaqueInput_OptimizationFlag |
246 kConstantOutputForConstantInput_OptimizationFlag
247 };
248 GR_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)
249
Brian Salomon6cd51b52017-07-26 19:07:15 -0400250 /**
251 * Can be used as a helper to decide which fragment processor OptimizationFlags should be set.
252 * This assumes that the subclass output color will be a modulation of the input color with a
253 * value read from a texture of the passed config and that the texture contains premultiplied
254 * color or alpha values that are in range.
255 */
256 static OptimizationFlags ModulateByConfigOptimizationFlags(GrPixelConfig config) {
257 if (GrPixelConfigIsOpaque(config)) {
258 return kCompatibleWithCoverageAsAlpha_OptimizationFlag |
259 kPreservesOpaqueInput_OptimizationFlag;
260 } else {
261 return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
262 }
263 }
264
Brian Salomon587e08f2017-01-27 10:59:27 -0500265 GrFragmentProcessor(OptimizationFlags optimizationFlags) : fFlags(optimizationFlags) {
266 SkASSERT((fFlags & ~kAll_OptimizationFlags) == 0);
267 }
268
269 OptimizationFlags optimizationFlags() const {
270 return static_cast<OptimizationFlags>(kAll_OptimizationFlags & fFlags);
271 }
272
273 /**
274 * This allows one subclass to access another subclass's implementation of
275 * constantOutputForConstantInput. It must only be called when
276 * hasConstantOutputForConstantInput() is known to be true.
277 */
278 static GrColor4f ConstantOutputForConstantInput(const GrFragmentProcessor& fp,
279 GrColor4f input) {
280 SkASSERT(fp.hasConstantOutputForConstantInput());
281 return fp.constantOutputForConstantInput(input);
282 }
283
bsalomon6251d172014-10-15 10:50:36 -0700284 /**
285 * Fragment Processor subclasses call this from their constructor to register coordinate
bsalomonde258cd2014-10-15 19:06:21 -0700286 * transformations. Coord transforms provide a mechanism for a processor to receive coordinates
287 * in their FS code. The matrix expresses a transformation from local space. For a given
288 * fragment the matrix will be applied to the local coordinate that maps to the fragment.
289 *
290 * When the transformation has perspective, the transformed coordinates will have
mtklein790d74f2015-08-19 11:05:39 -0700291 * 3 components. Otherwise they'll have 2.
bsalomonde258cd2014-10-15 19:06:21 -0700292 *
293 * This must only be called from the constructor because GrProcessors are immutable. The
294 * processor subclass manages the lifetime of the transformations (this function only stores a
mtklein790d74f2015-08-19 11:05:39 -0700295 * pointer). The GrCoordTransform is typically a member field of the GrProcessor subclass.
bsalomonde258cd2014-10-15 19:06:21 -0700296 *
297 * A processor subclass that has multiple methods of construction should always add its coord
298 * transforms in a consistent order. The non-virtual implementation of isEqual() automatically
299 * compares transforms and will assume they line up across the two processor instances.
bsalomon6251d172014-10-15 10:50:36 -0700300 */
301 void addCoordTransform(const GrCoordTransform*);
302
303 /**
wangyix58d890b2015-08-12 09:40:47 -0700304 * FragmentProcessor subclasses call this from their constructor to register any child
wangyix93ab2542015-08-19 08:23:12 -0700305 * FragmentProcessors they have. This must be called AFTER all texture accesses and coord
306 * transforms have been added.
wangyix4b3050b2015-08-04 07:59:37 -0700307 * This is for processors whose shader code will be composed of nested processors whose output
308 * colors will be combined somehow to produce its output color. Registering these child
wangyix58d890b2015-08-12 09:40:47 -0700309 * processors will allow the ProgramBuilder to automatically handle their transformed coords and
310 * texture accesses and mangle their uniform and output color names.
wangyix4b3050b2015-08-04 07:59:37 -0700311 */
bungeman06ca8ec2016-06-09 08:01:03 -0700312 int registerChildProcessor(sk_sp<GrFragmentProcessor> child);
wangyix4b3050b2015-08-04 07:59:37 -0700313
bsalomon6251d172014-10-15 10:50:36 -0700314private:
Brian Salomond61c9d92017-04-10 10:54:25 -0400315 void addPendingIOs() const override { GrResourceIOProcessor::addPendingIOs(); }
316 void removeRefs() const override { GrResourceIOProcessor::removeRefs(); }
317 void pendingIOComplete() const override { GrResourceIOProcessor::pendingIOComplete(); }
318
bsalomon42048002015-08-27 16:43:48 -0700319 void notifyRefCntIsZero() const final;
320
Brian Salomon587e08f2017-01-27 10:59:27 -0500321 virtual GrColor4f constantOutputForConstantInput(GrColor4f /* inputColor */) const {
322 SkFAIL("Subclass must override this if advertising this optimization.");
323 return GrColor4f::TransparentBlack();
324 }
325
wangyixb1daa862015-08-18 11:29:31 -0700326 /** Returns a new instance of the appropriate *GL* implementation class
327 for the given GrFragmentProcessor; caller is responsible for deleting
328 the object. */
egdaniel57d3b032015-11-13 11:57:27 -0800329 virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const = 0;
wangyixb1daa862015-08-18 11:29:31 -0700330
wangyix4b3050b2015-08-04 07:59:37 -0700331 /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */
Brian Salomon94efbf52016-11-29 13:43:05 -0500332 virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
wangyix4b3050b2015-08-04 07:59:37 -0700333
bsalomonde258cd2014-10-15 19:06:21 -0700334 /**
335 * Subclass implements this to support isEqual(). It will only be called if it is known that
336 * the two processors are of the same subclass (i.e. they return the same object from
337 * getFactory()). The processor subclass should not compare its coord transforms as that will
338 * be performed automatically in the non-virtual isEqual().
339 */
340 virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
341
342 bool hasSameTransforms(const GrFragmentProcessor&) const;
bsalomon6251d172014-10-15 10:50:36 -0700343
Brian Salomon587e08f2017-01-27 10:59:27 -0500344 enum PrivateFlags {
345 kFirstPrivateFlag = kAll_OptimizationFlags + 1,
346 kUsesLocalCoords_Flag = kFirstPrivateFlag,
Brian Salomon587e08f2017-01-27 10:59:27 -0500347 };
348
349 mutable uint32_t fFlags = 0;
wangyix58d890b2015-08-12 09:40:47 -0700350
bsalomona624bf32016-09-20 09:12:47 -0700351 SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms;
352
wangyix58d890b2015-08-12 09:40:47 -0700353 /**
bungeman06ca8ec2016-06-09 08:01:03 -0700354 * This is not SkSTArray<1, sk_sp<GrFragmentProcessor>> because this class holds strong
355 * references until notifyRefCntIsZero and then it holds pending executions.
356 */
Brian Salomon587e08f2017-01-27 10:59:27 -0500357 SkSTArray<1, GrFragmentProcessor*, true> fChildProcessors;
bsalomon6251d172014-10-15 10:50:36 -0700358
Robert Phillips9bee2e52017-05-29 12:37:20 -0400359 typedef GrResourceIOProcessor INHERITED;
bsalomon6251d172014-10-15 10:50:36 -0700360};
361
Brian Salomon587e08f2017-01-27 10:59:27 -0500362GR_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)
363
bsalomon6251d172014-10-15 10:50:36 -0700364#endif