blob: b875c7919f7bc8af583aea25a6f2d40f276ec589 [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;
Chris Dalton1c548942018-05-22 13:09:48 -060016class GrPaint;
bsalomona624bf32016-09-20 09:12:47 -070017class GrPipeline;
joshualitteb2a6762014-12-04 11:35:33 -080018class GrProcessorKeyBuilder;
Brian Salomon94efbf52016-11-29 13:43:05 -050019class GrShaderCaps;
Brian Osmance425512017-03-22 14:37:50 -040020class GrSwizzle;
bsalomon6251d172014-10-15 10:50:36 -070021
Ethan Nicholasf7b88202017-09-18 14:10:39 -040022/** Provides custom fragment shader code. Fragment processors receive an input color (half4) and
bsalomon6251d172014-10-15 10:50:36 -070023 produce an output color. They may reference textures and uniforms. They may use
24 GrCoordTransforms to receive a transformation of the local coordinates that map from local space
25 to the fragment being processed.
26 */
Brian Salomonaff329b2017-08-11 09:40:37 -040027class GrFragmentProcessor : public GrResourceIOProcessor {
bsalomon6251d172014-10-15 10:50:36 -070028public:
bsalomon87ba62e2015-09-22 06:41:59 -070029 /**
30 * In many instances (e.g. SkShader::asFragmentProcessor() implementations) it is desirable to
31 * only consider the input color's alpha. However, there is a competing desire to have reusable
32 * GrFragmentProcessor subclasses that can be used in other scenarios where the entire input
33 * color is considered. This function exists to filter the input color and pass it to a FP. It
34 * does so by returning a parent FP that multiplies the passed in FPs output by the parent's
35 * input alpha. The passed in FP will not receive an input color.
36 */
Mike Reed28eaed22018-02-01 11:24:53 -050037 static std::unique_ptr<GrFragmentProcessor> MulChildByInputAlpha(
38 std::unique_ptr<GrFragmentProcessor> child);
39
40 /**
41 * Like MulChildByInputAlpha(), but reverses the sense of src and dst. In this case, return
42 * the input modulated by the child's alpha. The passed in FP will not receive an input color.
43 *
44 * output = input * child.a
45 */
46 static std::unique_ptr<GrFragmentProcessor> MulInputByChildAlpha(
47 std::unique_ptr<GrFragmentProcessor> child);
bsalomonf1b7a1d2015-09-28 06:26:28 -070048
49 /**
Brian Salomon22af73f2017-01-26 11:25:12 -050050 * This assumes that the input color to the returned processor will be unpremul and that the
51 * passed processor (which becomes the returned processor's child) produces a premul output.
52 * The result of the returned processor is a premul of its input color modulated by the child
53 * processor's premul output.
bsalomonf1b7a1d2015-09-28 06:26:28 -070054 */
Brian Salomonaff329b2017-08-11 09:40:37 -040055 static std::unique_ptr<GrFragmentProcessor> MakeInputPremulAndMulByOutput(
56 std::unique_ptr<GrFragmentProcessor>);
bsalomonf1b7a1d2015-09-28 06:26:28 -070057
58 /**
bsalomone25eea42015-09-29 06:38:55 -070059 * Returns a parent fragment processor that adopts the passed fragment processor as a child.
60 * The parent will ignore its input color and instead feed the passed in color as input to the
61 * child.
bsalomonf1b7a1d2015-09-28 06:26:28 -070062 */
Brian Salomonaff329b2017-08-11 09:40:37 -040063 static std::unique_ptr<GrFragmentProcessor> OverrideInput(std::unique_ptr<GrFragmentProcessor>,
64 GrColor4f);
bsalomon87ba62e2015-09-22 06:41:59 -070065
bsalomone25eea42015-09-29 06:38:55 -070066 /**
dvonbeckc526da92016-07-20 11:20:30 -070067 * Returns a fragment processor that premuls the input before calling the passed in fragment
68 * processor.
69 */
Brian Salomonaff329b2017-08-11 09:40:37 -040070 static std::unique_ptr<GrFragmentProcessor> PremulInput(std::unique_ptr<GrFragmentProcessor>);
dvonbeckc526da92016-07-20 11:20:30 -070071
72 /**
Brian Osmande1a6052017-03-22 10:57:00 -040073 * Returns a fragment processor that calls the passed in fragment processor, and then premuls
74 * the output.
75 */
Brian Salomonaff329b2017-08-11 09:40:37 -040076 static std::unique_ptr<GrFragmentProcessor> PremulOutput(std::unique_ptr<GrFragmentProcessor>);
Brian Osmande1a6052017-03-22 10:57:00 -040077
78 /**
79 * Returns a fragment processor that calls the passed in fragment processor, and then unpremuls
80 * the output.
81 */
Brian Salomonaff329b2017-08-11 09:40:37 -040082 static std::unique_ptr<GrFragmentProcessor> UnpremulOutput(
83 std::unique_ptr<GrFragmentProcessor>);
Brian Osmande1a6052017-03-22 10:57:00 -040084
85 /**
Brian Osmance425512017-03-22 14:37:50 -040086 * Returns a fragment processor that calls the passed in fragment processor, and then swizzles
87 * the output.
88 */
Brian Salomonaff329b2017-08-11 09:40:37 -040089 static std::unique_ptr<GrFragmentProcessor> SwizzleOutput(std::unique_ptr<GrFragmentProcessor>,
90 const GrSwizzle&);
Brian Osmance425512017-03-22 14:37:50 -040091
92 /**
bsalomone25eea42015-09-29 06:38:55 -070093 * Returns a fragment processor that runs the passed in array of fragment processors in a
94 * series. The original input is passed to the first, the first's output is passed to the
95 * second, etc. The output of the returned processor is the output of the last processor of the
96 * series.
bungeman06ca8ec2016-06-09 08:01:03 -070097 *
98 * The array elements with be moved.
bsalomone25eea42015-09-29 06:38:55 -070099 */
Brian Salomonaff329b2017-08-11 09:40:37 -0400100 static std::unique_ptr<GrFragmentProcessor> RunInSeries(std::unique_ptr<GrFragmentProcessor>*,
101 int cnt);
bsalomonac856c92015-08-27 06:30:17 -0700102
Brian Salomon0e05a822017-07-25 09:43:22 -0400103 /**
104 * Makes a copy of this fragment processor that draws equivalently to the original.
Brian Salomon96271cd2017-07-31 16:27:23 -0400105 * If the processor has child processors they are cloned as well.
Brian Salomon0e05a822017-07-25 09:43:22 -0400106 */
Brian Salomonaff329b2017-08-11 09:40:37 -0400107 virtual std::unique_ptr<GrFragmentProcessor> clone() const = 0;
Brian Salomon0e05a822017-07-25 09:43:22 -0400108
egdaniel57d3b032015-11-13 11:57:27 -0800109 GrGLSLFragmentProcessor* createGLSLInstance() const;
joshualitteb2a6762014-12-04 11:35:33 -0800110
Brian Salomon94efbf52016-11-29 13:43:05 -0500111 void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
egdaniel57d3b032015-11-13 11:57:27 -0800112 this->onGetGLSLProcessorKey(caps, b);
wangyix4b3050b2015-08-04 07:59:37 -0700113 for (int i = 0; i < fChildProcessors.count(); ++i) {
egdaniel57d3b032015-11-13 11:57:27 -0800114 fChildProcessors[i]->getGLSLProcessorKey(caps, b);
wangyix4b3050b2015-08-04 07:59:37 -0700115 }
116 }
117
bsalomona624bf32016-09-20 09:12:47 -0700118 int numCoordTransforms() const { return fCoordTransforms.count(); }
bsalomon6251d172014-10-15 10:50:36 -0700119
120 /** Returns the coordinate transformation at index. index must be valid according to
121 numTransforms(). */
122 const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
123
joshualittabb52a12015-01-13 15:02:10 -0800124 const SkTArray<const GrCoordTransform*, true>& coordTransforms() const {
125 return fCoordTransforms;
126 }
127
wangyix4b3050b2015-08-04 07:59:37 -0700128 int numChildProcessors() const { return fChildProcessors.count(); }
129
bsalomonac856c92015-08-27 06:30:17 -0700130 const GrFragmentProcessor& childProcessor(int index) const { return *fChildProcessors[index]; }
wangyix4b3050b2015-08-04 07:59:37 -0700131
Robert Phillips9bee2e52017-05-29 12:37:20 -0400132 bool instantiate(GrResourceProvider*) const;
133
Brian Salomonaff329b2017-08-11 09:40:37 -0400134 void markPendingExecution() const;
135
joshualitt290c09b2014-12-19 13:45:20 -0800136 /** Do any of the coordtransforms for this processor require local coords? */
Brian Salomon587e08f2017-01-27 10:59:27 -0500137 bool usesLocalCoords() const { return SkToBool(fFlags & kUsesLocalCoords_Flag); }
joshualitt290c09b2014-12-19 13:45:20 -0800138
Brian Salomon587e08f2017-01-27 10:59:27 -0500139 /**
Brian Salomonf3b995b2017-02-15 10:22:23 -0500140 * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
141 * output under the following scenario:
142 * * all the color fragment processors report true to this query,
143 * * all the coverage fragment processors report true to this query,
144 * * the blend mode arithmetic allows for it it.
145 * To be compatible a fragment processor's output must be a modulation of its input color or
146 * alpha with a computed premultiplied color or alpha that is in 0..1 range. The computed color
147 * or alpha that is modulated against the input cannot depend on the input's alpha. The computed
148 * value cannot depend on the input's color channels unless it unpremultiplies the input color
149 * channels by the input alpha.
Brian Salomon587e08f2017-01-27 10:59:27 -0500150 */
Brian Salomonf3b995b2017-02-15 10:22:23 -0500151 bool compatibleWithCoverageAsAlpha() const {
152 return SkToBool(fFlags & kCompatibleWithCoverageAsAlpha_OptimizationFlag);
153 }
Brian Salomon587e08f2017-01-27 10:59:27 -0500154
155 /**
156 * If this is true then all opaque input colors to the processor produce opaque output colors.
157 */
158 bool preservesOpaqueInput() const {
159 return SkToBool(fFlags & kPreservesOpaqueInput_OptimizationFlag);
160 }
161
162 /**
163 * Tests whether given a constant input color the processor produces a constant output color
164 * (for all fragments). If true outputColor will contain the constant color produces for
165 * inputColor.
166 */
167 bool hasConstantOutputForConstantInput(GrColor4f inputColor, GrColor4f* outputColor) const {
168 if (fFlags & kConstantOutputForConstantInput_OptimizationFlag) {
169 *outputColor = this->constantOutputForConstantInput(inputColor);
170 return true;
171 }
172 return false;
173 }
174 bool hasConstantOutputForConstantInput() const {
175 return SkToBool(fFlags & kConstantOutputForConstantInput_OptimizationFlag);
176 }
dvonbeck9b03e7b2016-08-01 11:01:56 -0700177
joshualitteb2a6762014-12-04 11:35:33 -0800178 /** Returns true if this and other processor conservatively draw identically. It can only return
179 true when the two processor are of the same subclass (i.e. they return the same object from
bsalomon6251d172014-10-15 10:50:36 -0700180 from getFactory()).
181
joshualitteb2a6762014-12-04 11:35:33 -0800182 A return value of true from isEqual() should not be used to test whether the processor would
egdaniel57d3b032015-11-13 11:57:27 -0800183 generate the same shader code. To test for identical code generation use getGLSLProcessorKey
184 */
bsalomon7312ff82016-09-12 08:55:38 -0700185 bool isEqual(const GrFragmentProcessor& that) const;
bsalomon6251d172014-10-15 10:50:36 -0700186
joshualitt56995b52014-12-11 15:44:02 -0800187 /**
bsalomona624bf32016-09-20 09:12:47 -0700188 * Pre-order traversal of a FP hierarchy, or of the forest of FPs in a GrPipeline. In the latter
189 * case the tree rooted at each FP in the GrPipeline is visited successively.
bsalomonb58a2b42016-09-26 06:55:02 -0700190 */
bsalomona624bf32016-09-20 09:12:47 -0700191 class Iter : public SkNoncopyable {
192 public:
193 explicit Iter(const GrFragmentProcessor* fp) { fFPStack.push_back(fp); }
194 explicit Iter(const GrPipeline& pipeline);
Chris Dalton1c548942018-05-22 13:09:48 -0600195 explicit Iter(const GrPaint&);
bsalomona624bf32016-09-20 09:12:47 -0700196 const GrFragmentProcessor* next();
197
198 private:
199 SkSTArray<4, const GrFragmentProcessor*, true> fFPStack;
200 };
201
202 /**
bsalomonb58a2b42016-09-26 06:55:02 -0700203 * Iterates over all the Ts owned by a GrFragmentProcessor and its children or over all the Ts
204 * owned by the forest of GrFragmentProcessors in a GrPipeline. FPs are visited in the same
205 * order as Iter and each of an FP's Ts are visited in order.
bsalomona624bf32016-09-20 09:12:47 -0700206 */
bsalomonb58a2b42016-09-26 06:55:02 -0700207 template <typename T, typename BASE,
208 int (BASE::*COUNT)() const,
209 const T& (BASE::*GET)(int) const>
210 class FPItemIter : public SkNoncopyable {
bsalomona624bf32016-09-20 09:12:47 -0700211 public:
bsalomonb58a2b42016-09-26 06:55:02 -0700212 explicit FPItemIter(const GrFragmentProcessor* fp)
213 : fCurrFP(nullptr)
214 , fCTIdx(0)
215 , fFPIter(fp) {
216 fCurrFP = fFPIter.next();
217 }
218 explicit FPItemIter(const GrPipeline& pipeline)
bsalomona624bf32016-09-20 09:12:47 -0700219 : fCurrFP(nullptr)
220 , fCTIdx(0)
221 , fFPIter(pipeline) {
222 fCurrFP = fFPIter.next();
223 }
bsalomonb58a2b42016-09-26 06:55:02 -0700224
225 const T* next() {
226 if (!fCurrFP) {
227 return nullptr;
228 }
229 while (fCTIdx == (fCurrFP->*COUNT)()) {
230 fCTIdx = 0;
231 fCurrFP = fFPIter.next();
232 if (!fCurrFP) {
233 return nullptr;
234 }
235 }
236 return &(fCurrFP->*GET)(fCTIdx++);
237 }
bsalomona624bf32016-09-20 09:12:47 -0700238
239 private:
240 const GrFragmentProcessor* fCurrFP;
241 int fCTIdx;
242 GrFragmentProcessor::Iter fFPIter;
243 };
244
bsalomonb58a2b42016-09-26 06:55:02 -0700245 using CoordTransformIter = FPItemIter<GrCoordTransform,
246 GrFragmentProcessor,
247 &GrFragmentProcessor::numCoordTransforms,
248 &GrFragmentProcessor::coordTransform>;
249
Brian Salomon0bbecb22016-11-17 11:38:22 -0500250 using TextureAccessIter = FPItemIter<TextureSampler,
Brian Salomonab015ef2017-04-04 10:15:51 -0400251 GrResourceIOProcessor,
252 &GrResourceIOProcessor::numTextureSamplers,
253 &GrResourceIOProcessor::textureSampler>;
bsalomonb58a2b42016-09-26 06:55:02 -0700254
Robert Phillipsf1748f52017-09-14 14:11:24 -0400255 void visitProxies(const std::function<void(GrSurfaceProxy*)>& func) {
Robert Phillipsb493eeb2017-09-13 13:10:52 -0400256 GrFragmentProcessor::TextureAccessIter iter(this);
257 while (const GrResourceIOProcessor::TextureSampler* sampler = iter.next()) {
258 func(sampler->proxy());
259 }
260 }
261
bsalomon6251d172014-10-15 10:50:36 -0700262protected:
Brian Salomon587e08f2017-01-27 10:59:27 -0500263 enum OptimizationFlags : uint32_t {
264 kNone_OptimizationFlags,
Brian Salomonf3b995b2017-02-15 10:22:23 -0500265 kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1,
Brian Salomon587e08f2017-01-27 10:59:27 -0500266 kPreservesOpaqueInput_OptimizationFlag = 0x2,
267 kConstantOutputForConstantInput_OptimizationFlag = 0x4,
Brian Salomonf3b995b2017-02-15 10:22:23 -0500268 kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag |
Brian Salomon587e08f2017-01-27 10:59:27 -0500269 kPreservesOpaqueInput_OptimizationFlag |
270 kConstantOutputForConstantInput_OptimizationFlag
271 };
272 GR_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)
273
Brian Salomon6cd51b52017-07-26 19:07:15 -0400274 /**
275 * Can be used as a helper to decide which fragment processor OptimizationFlags should be set.
276 * This assumes that the subclass output color will be a modulation of the input color with a
277 * value read from a texture of the passed config and that the texture contains premultiplied
278 * color or alpha values that are in range.
279 */
280 static OptimizationFlags ModulateByConfigOptimizationFlags(GrPixelConfig config) {
281 if (GrPixelConfigIsOpaque(config)) {
282 return kCompatibleWithCoverageAsAlpha_OptimizationFlag |
283 kPreservesOpaqueInput_OptimizationFlag;
284 } else {
285 return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
286 }
287 }
288
Ethan Nicholasabff9562017-10-09 10:54:08 -0400289 GrFragmentProcessor(ClassID classID, OptimizationFlags optimizationFlags)
290 : INHERITED(classID)
291 , fFlags(optimizationFlags) {
Brian Salomon587e08f2017-01-27 10:59:27 -0500292 SkASSERT((fFlags & ~kAll_OptimizationFlags) == 0);
293 }
294
295 OptimizationFlags optimizationFlags() const {
296 return static_cast<OptimizationFlags>(kAll_OptimizationFlags & fFlags);
297 }
298
299 /**
300 * This allows one subclass to access another subclass's implementation of
301 * constantOutputForConstantInput. It must only be called when
302 * hasConstantOutputForConstantInput() is known to be true.
303 */
304 static GrColor4f ConstantOutputForConstantInput(const GrFragmentProcessor& fp,
305 GrColor4f input) {
306 SkASSERT(fp.hasConstantOutputForConstantInput());
307 return fp.constantOutputForConstantInput(input);
308 }
309
bsalomon6251d172014-10-15 10:50:36 -0700310 /**
311 * Fragment Processor subclasses call this from their constructor to register coordinate
bsalomonde258cd2014-10-15 19:06:21 -0700312 * transformations. Coord transforms provide a mechanism for a processor to receive coordinates
313 * in their FS code. The matrix expresses a transformation from local space. For a given
314 * fragment the matrix will be applied to the local coordinate that maps to the fragment.
315 *
316 * When the transformation has perspective, the transformed coordinates will have
mtklein790d74f2015-08-19 11:05:39 -0700317 * 3 components. Otherwise they'll have 2.
bsalomonde258cd2014-10-15 19:06:21 -0700318 *
319 * This must only be called from the constructor because GrProcessors are immutable. The
320 * processor subclass manages the lifetime of the transformations (this function only stores a
mtklein790d74f2015-08-19 11:05:39 -0700321 * pointer). The GrCoordTransform is typically a member field of the GrProcessor subclass.
bsalomonde258cd2014-10-15 19:06:21 -0700322 *
323 * A processor subclass that has multiple methods of construction should always add its coord
324 * transforms in a consistent order. The non-virtual implementation of isEqual() automatically
325 * compares transforms and will assume they line up across the two processor instances.
bsalomon6251d172014-10-15 10:50:36 -0700326 */
327 void addCoordTransform(const GrCoordTransform*);
328
329 /**
wangyix58d890b2015-08-12 09:40:47 -0700330 * FragmentProcessor subclasses call this from their constructor to register any child
wangyix93ab2542015-08-19 08:23:12 -0700331 * FragmentProcessors they have. This must be called AFTER all texture accesses and coord
332 * transforms have been added.
wangyix4b3050b2015-08-04 07:59:37 -0700333 * This is for processors whose shader code will be composed of nested processors whose output
334 * colors will be combined somehow to produce its output color. Registering these child
wangyix58d890b2015-08-12 09:40:47 -0700335 * processors will allow the ProgramBuilder to automatically handle their transformed coords and
336 * texture accesses and mangle their uniform and output color names.
wangyix4b3050b2015-08-04 07:59:37 -0700337 */
Brian Salomonaff329b2017-08-11 09:40:37 -0400338 int registerChildProcessor(std::unique_ptr<GrFragmentProcessor> child);
wangyix4b3050b2015-08-04 07:59:37 -0700339
bsalomon6251d172014-10-15 10:50:36 -0700340private:
Brian Salomon587e08f2017-01-27 10:59:27 -0500341 virtual GrColor4f constantOutputForConstantInput(GrColor4f /* inputColor */) const {
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400342 SK_ABORT("Subclass must override this if advertising this optimization.");
Brian Salomon587e08f2017-01-27 10:59:27 -0500343 return GrColor4f::TransparentBlack();
344 }
345
wangyixb1daa862015-08-18 11:29:31 -0700346 /** Returns a new instance of the appropriate *GL* implementation class
347 for the given GrFragmentProcessor; caller is responsible for deleting
348 the object. */
egdaniel57d3b032015-11-13 11:57:27 -0800349 virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const = 0;
wangyixb1daa862015-08-18 11:29:31 -0700350
wangyix4b3050b2015-08-04 07:59:37 -0700351 /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */
Brian Salomon94efbf52016-11-29 13:43:05 -0500352 virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
wangyix4b3050b2015-08-04 07:59:37 -0700353
bsalomonde258cd2014-10-15 19:06:21 -0700354 /**
355 * Subclass implements this to support isEqual(). It will only be called if it is known that
356 * the two processors are of the same subclass (i.e. they return the same object from
357 * getFactory()). The processor subclass should not compare its coord transforms as that will
358 * be performed automatically in the non-virtual isEqual().
359 */
360 virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
361
362 bool hasSameTransforms(const GrFragmentProcessor&) const;
bsalomon6251d172014-10-15 10:50:36 -0700363
Brian Salomon587e08f2017-01-27 10:59:27 -0500364 enum PrivateFlags {
365 kFirstPrivateFlag = kAll_OptimizationFlags + 1,
366 kUsesLocalCoords_Flag = kFirstPrivateFlag,
Brian Salomon587e08f2017-01-27 10:59:27 -0500367 };
368
369 mutable uint32_t fFlags = 0;
wangyix58d890b2015-08-12 09:40:47 -0700370
bsalomona624bf32016-09-20 09:12:47 -0700371 SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms;
372
Brian Salomonaff329b2017-08-11 09:40:37 -0400373 SkSTArray<1, std::unique_ptr<GrFragmentProcessor>, true> fChildProcessors;
bsalomon6251d172014-10-15 10:50:36 -0700374
Robert Phillips9bee2e52017-05-29 12:37:20 -0400375 typedef GrResourceIOProcessor INHERITED;
bsalomon6251d172014-10-15 10:50:36 -0700376};
377
Brian Salomon587e08f2017-01-27 10:59:27 -0500378GR_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)
379
bsalomon6251d172014-10-15 10:50:36 -0700380#endif