blob: 55dc08f7a08abf416778b28c516f72615bdfc23d [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;
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 /**
Brian Salomon22af73f2017-01-26 11:25:12 -050038 * This assumes that the input color to the returned processor will be unpremul and that the
39 * passed processor (which becomes the returned processor's child) produces a premul output.
40 * The result of the returned processor is a premul of its input color modulated by the child
41 * processor's premul output.
bsalomonf1b7a1d2015-09-28 06:26:28 -070042 */
Brian Salomon22af73f2017-01-26 11:25:12 -050043 static sk_sp<GrFragmentProcessor> MakeInputPremulAndMulByOutput(sk_sp<GrFragmentProcessor>);
bsalomonf1b7a1d2015-09-28 06:26:28 -070044
45 /**
bsalomone25eea42015-09-29 06:38:55 -070046 * Returns a parent fragment processor that adopts the passed fragment processor as a child.
47 * The parent will ignore its input color and instead feed the passed in color as input to the
48 * child.
bsalomonf1b7a1d2015-09-28 06:26:28 -070049 */
brianosman4cea3b92016-09-08 09:33:50 -070050 static sk_sp<GrFragmentProcessor> OverrideInput(sk_sp<GrFragmentProcessor>, GrColor4f);
bsalomon87ba62e2015-09-22 06:41:59 -070051
bsalomone25eea42015-09-29 06:38:55 -070052 /**
dvonbeckc526da92016-07-20 11:20:30 -070053 * Returns a fragment processor that premuls the input before calling the passed in fragment
54 * processor.
55 */
56 static sk_sp<GrFragmentProcessor> PremulInput(sk_sp<GrFragmentProcessor>);
57
58 /**
bsalomone25eea42015-09-29 06:38:55 -070059 * Returns a fragment processor that runs the passed in array of fragment processors in a
60 * series. The original input is passed to the first, the first's output is passed to the
61 * second, etc. The output of the returned processor is the output of the last processor of the
62 * series.
bungeman06ca8ec2016-06-09 08:01:03 -070063 *
64 * The array elements with be moved.
bsalomone25eea42015-09-29 06:38:55 -070065 */
bungeman06ca8ec2016-06-09 08:01:03 -070066 static sk_sp<GrFragmentProcessor> RunInSeries(sk_sp<GrFragmentProcessor>*, int cnt);
bsalomone25eea42015-09-29 06:38:55 -070067
bsalomonac856c92015-08-27 06:30:17 -070068 ~GrFragmentProcessor() override;
69
egdaniel57d3b032015-11-13 11:57:27 -080070 GrGLSLFragmentProcessor* createGLSLInstance() const;
joshualitteb2a6762014-12-04 11:35:33 -080071
Brian Salomon94efbf52016-11-29 13:43:05 -050072 void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
egdaniel57d3b032015-11-13 11:57:27 -080073 this->onGetGLSLProcessorKey(caps, b);
wangyix4b3050b2015-08-04 07:59:37 -070074 for (int i = 0; i < fChildProcessors.count(); ++i) {
egdaniel57d3b032015-11-13 11:57:27 -080075 fChildProcessors[i]->getGLSLProcessorKey(caps, b);
wangyix4b3050b2015-08-04 07:59:37 -070076 }
77 }
78
bsalomona624bf32016-09-20 09:12:47 -070079 int numCoordTransforms() const { return fCoordTransforms.count(); }
bsalomon6251d172014-10-15 10:50:36 -070080
81 /** Returns the coordinate transformation at index. index must be valid according to
82 numTransforms(). */
83 const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
84
joshualittabb52a12015-01-13 15:02:10 -080085 const SkTArray<const GrCoordTransform*, true>& coordTransforms() const {
86 return fCoordTransforms;
87 }
88
wangyix4b3050b2015-08-04 07:59:37 -070089 int numChildProcessors() const { return fChildProcessors.count(); }
90
bsalomonac856c92015-08-27 06:30:17 -070091 const GrFragmentProcessor& childProcessor(int index) const { return *fChildProcessors[index]; }
wangyix4b3050b2015-08-04 07:59:37 -070092
joshualitt290c09b2014-12-19 13:45:20 -080093 /** Do any of the coordtransforms for this processor require local coords? */
Brian Salomon587e08f2017-01-27 10:59:27 -050094 bool usesLocalCoords() const { return SkToBool(fFlags & kUsesLocalCoords_Flag); }
joshualitt290c09b2014-12-19 13:45:20 -080095
dvonbeck9b03e7b2016-08-01 11:01:56 -070096 /** Does this FP need a vector to the nearest edge? */
Brian Salomon587e08f2017-01-27 10:59:27 -050097 bool usesDistanceVectorField() const {
98 return SkToBool(fFlags & kUsesDistanceVectorField_Flag);
99 }
100
101 /**
Brian Salomonf3b995b2017-02-15 10:22:23 -0500102 * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
103 * output under the following scenario:
104 * * all the color fragment processors report true to this query,
105 * * all the coverage fragment processors report true to this query,
106 * * the blend mode arithmetic allows for it it.
107 * To be compatible a fragment processor's output must be a modulation of its input color or
108 * alpha with a computed premultiplied color or alpha that is in 0..1 range. The computed color
109 * or alpha that is modulated against the input cannot depend on the input's alpha. The computed
110 * value cannot depend on the input's color channels unless it unpremultiplies the input color
111 * channels by the input alpha.
Brian Salomon587e08f2017-01-27 10:59:27 -0500112 */
Brian Salomonf3b995b2017-02-15 10:22:23 -0500113 bool compatibleWithCoverageAsAlpha() const {
114 return SkToBool(fFlags & kCompatibleWithCoverageAsAlpha_OptimizationFlag);
115 }
Brian Salomon587e08f2017-01-27 10:59:27 -0500116
117 /**
118 * If this is true then all opaque input colors to the processor produce opaque output colors.
119 */
120 bool preservesOpaqueInput() const {
121 return SkToBool(fFlags & kPreservesOpaqueInput_OptimizationFlag);
122 }
123
124 /**
125 * Tests whether given a constant input color the processor produces a constant output color
126 * (for all fragments). If true outputColor will contain the constant color produces for
127 * inputColor.
128 */
129 bool hasConstantOutputForConstantInput(GrColor4f inputColor, GrColor4f* outputColor) const {
130 if (fFlags & kConstantOutputForConstantInput_OptimizationFlag) {
131 *outputColor = this->constantOutputForConstantInput(inputColor);
132 return true;
133 }
134 return false;
135 }
136 bool hasConstantOutputForConstantInput() const {
137 return SkToBool(fFlags & kConstantOutputForConstantInput_OptimizationFlag);
138 }
dvonbeck9b03e7b2016-08-01 11:01:56 -0700139
joshualitteb2a6762014-12-04 11:35:33 -0800140 /** Returns true if this and other processor conservatively draw identically. It can only return
141 true when the two processor are of the same subclass (i.e. they return the same object from
bsalomon6251d172014-10-15 10:50:36 -0700142 from getFactory()).
143
joshualitteb2a6762014-12-04 11:35:33 -0800144 A return value of true from isEqual() should not be used to test whether the processor would
egdaniel57d3b032015-11-13 11:57:27 -0800145 generate the same shader code. To test for identical code generation use getGLSLProcessorKey
146 */
bsalomon7312ff82016-09-12 08:55:38 -0700147 bool isEqual(const GrFragmentProcessor& that) const;
bsalomon6251d172014-10-15 10:50:36 -0700148
joshualitt56995b52014-12-11 15:44:02 -0800149 /**
bsalomona624bf32016-09-20 09:12:47 -0700150 * Pre-order traversal of a FP hierarchy, or of the forest of FPs in a GrPipeline. In the latter
151 * case the tree rooted at each FP in the GrPipeline is visited successively.
bsalomonb58a2b42016-09-26 06:55:02 -0700152 */
bsalomona624bf32016-09-20 09:12:47 -0700153 class Iter : public SkNoncopyable {
154 public:
155 explicit Iter(const GrFragmentProcessor* fp) { fFPStack.push_back(fp); }
156 explicit Iter(const GrPipeline& pipeline);
157 const GrFragmentProcessor* next();
158
159 private:
160 SkSTArray<4, const GrFragmentProcessor*, true> fFPStack;
161 };
162
163 /**
bsalomonb58a2b42016-09-26 06:55:02 -0700164 * Iterates over all the Ts owned by a GrFragmentProcessor and its children or over all the Ts
165 * owned by the forest of GrFragmentProcessors in a GrPipeline. FPs are visited in the same
166 * order as Iter and each of an FP's Ts are visited in order.
bsalomona624bf32016-09-20 09:12:47 -0700167 */
bsalomonb58a2b42016-09-26 06:55:02 -0700168 template <typename T, typename BASE,
169 int (BASE::*COUNT)() const,
170 const T& (BASE::*GET)(int) const>
171 class FPItemIter : public SkNoncopyable {
bsalomona624bf32016-09-20 09:12:47 -0700172 public:
bsalomonb58a2b42016-09-26 06:55:02 -0700173 explicit FPItemIter(const GrFragmentProcessor* fp)
174 : fCurrFP(nullptr)
175 , fCTIdx(0)
176 , fFPIter(fp) {
177 fCurrFP = fFPIter.next();
178 }
179 explicit FPItemIter(const GrPipeline& pipeline)
bsalomona624bf32016-09-20 09:12:47 -0700180 : fCurrFP(nullptr)
181 , fCTIdx(0)
182 , fFPIter(pipeline) {
183 fCurrFP = fFPIter.next();
184 }
bsalomonb58a2b42016-09-26 06:55:02 -0700185
186 const T* next() {
187 if (!fCurrFP) {
188 return nullptr;
189 }
190 while (fCTIdx == (fCurrFP->*COUNT)()) {
191 fCTIdx = 0;
192 fCurrFP = fFPIter.next();
193 if (!fCurrFP) {
194 return nullptr;
195 }
196 }
197 return &(fCurrFP->*GET)(fCTIdx++);
198 }
bsalomona624bf32016-09-20 09:12:47 -0700199
200 private:
201 const GrFragmentProcessor* fCurrFP;
202 int fCTIdx;
203 GrFragmentProcessor::Iter fFPIter;
204 };
205
bsalomonb58a2b42016-09-26 06:55:02 -0700206 using CoordTransformIter = FPItemIter<GrCoordTransform,
207 GrFragmentProcessor,
208 &GrFragmentProcessor::numCoordTransforms,
209 &GrFragmentProcessor::coordTransform>;
210
Brian Salomon0bbecb22016-11-17 11:38:22 -0500211 using TextureAccessIter = FPItemIter<TextureSampler,
bsalomonb58a2b42016-09-26 06:55:02 -0700212 GrProcessor,
Brian Salomon0bbecb22016-11-17 11:38:22 -0500213 &GrProcessor::numTextureSamplers,
214 &GrProcessor::textureSampler>;
bsalomonb58a2b42016-09-26 06:55:02 -0700215
bsalomon6251d172014-10-15 10:50:36 -0700216protected:
Brian Salomon587e08f2017-01-27 10:59:27 -0500217 enum OptimizationFlags : uint32_t {
218 kNone_OptimizationFlags,
Brian Salomonf3b995b2017-02-15 10:22:23 -0500219 kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1,
Brian Salomon587e08f2017-01-27 10:59:27 -0500220 kPreservesOpaqueInput_OptimizationFlag = 0x2,
221 kConstantOutputForConstantInput_OptimizationFlag = 0x4,
Brian Salomonf3b995b2017-02-15 10:22:23 -0500222 kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag |
Brian Salomon587e08f2017-01-27 10:59:27 -0500223 kPreservesOpaqueInput_OptimizationFlag |
224 kConstantOutputForConstantInput_OptimizationFlag
225 };
226 GR_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)
227
228 GrFragmentProcessor(OptimizationFlags optimizationFlags) : fFlags(optimizationFlags) {
229 SkASSERT((fFlags & ~kAll_OptimizationFlags) == 0);
230 }
231
232 OptimizationFlags optimizationFlags() const {
233 return static_cast<OptimizationFlags>(kAll_OptimizationFlags & fFlags);
234 }
235
236 /**
237 * This allows one subclass to access another subclass's implementation of
238 * constantOutputForConstantInput. It must only be called when
239 * hasConstantOutputForConstantInput() is known to be true.
240 */
241 static GrColor4f ConstantOutputForConstantInput(const GrFragmentProcessor& fp,
242 GrColor4f input) {
243 SkASSERT(fp.hasConstantOutputForConstantInput());
244 return fp.constantOutputForConstantInput(input);
245 }
246
bsalomon6251d172014-10-15 10:50:36 -0700247 /**
248 * Fragment Processor subclasses call this from their constructor to register coordinate
bsalomonde258cd2014-10-15 19:06:21 -0700249 * transformations. Coord transforms provide a mechanism for a processor to receive coordinates
250 * in their FS code. The matrix expresses a transformation from local space. For a given
251 * fragment the matrix will be applied to the local coordinate that maps to the fragment.
252 *
253 * When the transformation has perspective, the transformed coordinates will have
mtklein790d74f2015-08-19 11:05:39 -0700254 * 3 components. Otherwise they'll have 2.
bsalomonde258cd2014-10-15 19:06:21 -0700255 *
256 * This must only be called from the constructor because GrProcessors are immutable. The
257 * processor subclass manages the lifetime of the transformations (this function only stores a
mtklein790d74f2015-08-19 11:05:39 -0700258 * pointer). The GrCoordTransform is typically a member field of the GrProcessor subclass.
bsalomonde258cd2014-10-15 19:06:21 -0700259 *
260 * A processor subclass that has multiple methods of construction should always add its coord
261 * transforms in a consistent order. The non-virtual implementation of isEqual() automatically
262 * compares transforms and will assume they line up across the two processor instances.
bsalomon6251d172014-10-15 10:50:36 -0700263 */
264 void addCoordTransform(const GrCoordTransform*);
265
266 /**
wangyix58d890b2015-08-12 09:40:47 -0700267 * FragmentProcessor subclasses call this from their constructor to register any child
wangyix93ab2542015-08-19 08:23:12 -0700268 * FragmentProcessors they have. This must be called AFTER all texture accesses and coord
269 * transforms have been added.
wangyix4b3050b2015-08-04 07:59:37 -0700270 * This is for processors whose shader code will be composed of nested processors whose output
271 * colors will be combined somehow to produce its output color. Registering these child
wangyix58d890b2015-08-12 09:40:47 -0700272 * processors will allow the ProgramBuilder to automatically handle their transformed coords and
273 * texture accesses and mangle their uniform and output color names.
wangyix4b3050b2015-08-04 07:59:37 -0700274 */
bungeman06ca8ec2016-06-09 08:01:03 -0700275 int registerChildProcessor(sk_sp<GrFragmentProcessor> child);
wangyix4b3050b2015-08-04 07:59:37 -0700276
277 /**
Brian Salomon587e08f2017-01-27 10:59:27 -0500278 * Sub-classes should call this in their constructors if they need access to a distance
dvonbeck9b03e7b2016-08-01 11:01:56 -0700279 * vector field to the nearest edge
280 */
Brian Salomon587e08f2017-01-27 10:59:27 -0500281 void setWillUseDistanceVectorField() { fFlags |= kUsesDistanceVectorField_Flag; }
dvonbeck9b03e7b2016-08-01 11:01:56 -0700282
bsalomon6251d172014-10-15 10:50:36 -0700283private:
bsalomon42048002015-08-27 16:43:48 -0700284 void notifyRefCntIsZero() const final;
285
Brian Salomon587e08f2017-01-27 10:59:27 -0500286 virtual GrColor4f constantOutputForConstantInput(GrColor4f /* inputColor */) const {
287 SkFAIL("Subclass must override this if advertising this optimization.");
288 return GrColor4f::TransparentBlack();
289 }
290
wangyixb1daa862015-08-18 11:29:31 -0700291 /** Returns a new instance of the appropriate *GL* implementation class
292 for the given GrFragmentProcessor; caller is responsible for deleting
293 the object. */
egdaniel57d3b032015-11-13 11:57:27 -0800294 virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const = 0;
wangyixb1daa862015-08-18 11:29:31 -0700295
wangyix4b3050b2015-08-04 07:59:37 -0700296 /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */
Brian Salomon94efbf52016-11-29 13:43:05 -0500297 virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
wangyix4b3050b2015-08-04 07:59:37 -0700298
bsalomonde258cd2014-10-15 19:06:21 -0700299 /**
300 * Subclass implements this to support isEqual(). It will only be called if it is known that
301 * the two processors are of the same subclass (i.e. they return the same object from
302 * getFactory()). The processor subclass should not compare its coord transforms as that will
303 * be performed automatically in the non-virtual isEqual().
304 */
305 virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
306
307 bool hasSameTransforms(const GrFragmentProcessor&) const;
bsalomon6251d172014-10-15 10:50:36 -0700308
Brian Salomon587e08f2017-01-27 10:59:27 -0500309 enum PrivateFlags {
310 kFirstPrivateFlag = kAll_OptimizationFlags + 1,
311 kUsesLocalCoords_Flag = kFirstPrivateFlag,
312 kUsesDistanceVectorField_Flag = kFirstPrivateFlag << 1,
313 };
314
315 mutable uint32_t fFlags = 0;
wangyix58d890b2015-08-12 09:40:47 -0700316
bsalomona624bf32016-09-20 09:12:47 -0700317 SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms;
318
wangyix58d890b2015-08-12 09:40:47 -0700319 /**
bungeman06ca8ec2016-06-09 08:01:03 -0700320 * This is not SkSTArray<1, sk_sp<GrFragmentProcessor>> because this class holds strong
321 * references until notifyRefCntIsZero and then it holds pending executions.
322 */
Brian Salomon587e08f2017-01-27 10:59:27 -0500323 SkSTArray<1, GrFragmentProcessor*, true> fChildProcessors;
bsalomon6251d172014-10-15 10:50:36 -0700324
325 typedef GrProcessor INHERITED;
326};
327
Brian Salomon587e08f2017-01-27 10:59:27 -0500328GR_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)
329
bsalomon6251d172014-10-15 10:50:36 -0700330#endif