blob: 4ec92627ad987b9c230c1a68c250e154f51897b9 [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 Nicholasf7b88202017-09-18 14:10:39 -040021/** Provides custom fragment shader code. Fragment processors receive an input color (half4) 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 Salomonaff329b2017-08-11 09:40:37 -040026class GrFragmentProcessor : public GrResourceIOProcessor {
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 */
Brian Salomonaff329b2017-08-11 09:40:37 -040036 static std::unique_ptr<GrFragmentProcessor> MulOutputByInputAlpha(
37 std::unique_ptr<GrFragmentProcessor>);
bsalomonf1b7a1d2015-09-28 06:26:28 -070038
39 /**
Brian Salomon22af73f2017-01-26 11:25:12 -050040 * This assumes that the input color to the returned processor will be unpremul and that the
41 * passed processor (which becomes the returned processor's child) produces a premul output.
42 * The result of the returned processor is a premul of its input color modulated by the child
43 * processor's premul output.
bsalomonf1b7a1d2015-09-28 06:26:28 -070044 */
Brian Salomonaff329b2017-08-11 09:40:37 -040045 static std::unique_ptr<GrFragmentProcessor> MakeInputPremulAndMulByOutput(
46 std::unique_ptr<GrFragmentProcessor>);
bsalomonf1b7a1d2015-09-28 06:26:28 -070047
48 /**
bsalomone25eea42015-09-29 06:38:55 -070049 * Returns a parent fragment processor that adopts the passed fragment processor as a child.
50 * The parent will ignore its input color and instead feed the passed in color as input to the
51 * child.
bsalomonf1b7a1d2015-09-28 06:26:28 -070052 */
Brian Salomonaff329b2017-08-11 09:40:37 -040053 static std::unique_ptr<GrFragmentProcessor> OverrideInput(std::unique_ptr<GrFragmentProcessor>,
54 GrColor4f);
bsalomon87ba62e2015-09-22 06:41:59 -070055
bsalomone25eea42015-09-29 06:38:55 -070056 /**
dvonbeckc526da92016-07-20 11:20:30 -070057 * Returns a fragment processor that premuls the input before calling the passed in fragment
58 * processor.
59 */
Brian Salomonaff329b2017-08-11 09:40:37 -040060 static std::unique_ptr<GrFragmentProcessor> PremulInput(std::unique_ptr<GrFragmentProcessor>);
dvonbeckc526da92016-07-20 11:20:30 -070061
62 /**
Brian Osmande1a6052017-03-22 10:57:00 -040063 * Returns a fragment processor that calls the passed in fragment processor, and then premuls
64 * the output.
65 */
Brian Salomonaff329b2017-08-11 09:40:37 -040066 static std::unique_ptr<GrFragmentProcessor> PremulOutput(std::unique_ptr<GrFragmentProcessor>);
Brian Osmande1a6052017-03-22 10:57:00 -040067
68 /**
69 * Returns a fragment processor that calls the passed in fragment processor, and then unpremuls
70 * the output.
71 */
Brian Salomonaff329b2017-08-11 09:40:37 -040072 static std::unique_ptr<GrFragmentProcessor> UnpremulOutput(
73 std::unique_ptr<GrFragmentProcessor>);
Brian Osmande1a6052017-03-22 10:57:00 -040074
75 /**
Brian Osmance425512017-03-22 14:37:50 -040076 * Returns a fragment processor that calls the passed in fragment processor, and then swizzles
77 * the output.
78 */
Brian Salomonaff329b2017-08-11 09:40:37 -040079 static std::unique_ptr<GrFragmentProcessor> SwizzleOutput(std::unique_ptr<GrFragmentProcessor>,
80 const GrSwizzle&);
Brian Osmance425512017-03-22 14:37:50 -040081
82 /**
bsalomone25eea42015-09-29 06:38:55 -070083 * Returns a fragment processor that runs the passed in array of fragment processors in a
84 * series. The original input is passed to the first, the first's output is passed to the
85 * second, etc. The output of the returned processor is the output of the last processor of the
86 * series.
bungeman06ca8ec2016-06-09 08:01:03 -070087 *
88 * The array elements with be moved.
bsalomone25eea42015-09-29 06:38:55 -070089 */
Brian Salomonaff329b2017-08-11 09:40:37 -040090 static std::unique_ptr<GrFragmentProcessor> RunInSeries(std::unique_ptr<GrFragmentProcessor>*,
91 int cnt);
bsalomonac856c92015-08-27 06:30:17 -070092
Brian Salomon0e05a822017-07-25 09:43:22 -040093 /**
94 * Makes a copy of this fragment processor that draws equivalently to the original.
Brian Salomon96271cd2017-07-31 16:27:23 -040095 * If the processor has child processors they are cloned as well.
Brian Salomon0e05a822017-07-25 09:43:22 -040096 */
Brian Salomonaff329b2017-08-11 09:40:37 -040097 virtual std::unique_ptr<GrFragmentProcessor> clone() const = 0;
Brian Salomon0e05a822017-07-25 09:43:22 -040098
egdaniel57d3b032015-11-13 11:57:27 -080099 GrGLSLFragmentProcessor* createGLSLInstance() const;
joshualitteb2a6762014-12-04 11:35:33 -0800100
Brian Salomon94efbf52016-11-29 13:43:05 -0500101 void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
egdaniel57d3b032015-11-13 11:57:27 -0800102 this->onGetGLSLProcessorKey(caps, b);
wangyix4b3050b2015-08-04 07:59:37 -0700103 for (int i = 0; i < fChildProcessors.count(); ++i) {
egdaniel57d3b032015-11-13 11:57:27 -0800104 fChildProcessors[i]->getGLSLProcessorKey(caps, b);
wangyix4b3050b2015-08-04 07:59:37 -0700105 }
106 }
107
bsalomona624bf32016-09-20 09:12:47 -0700108 int numCoordTransforms() const { return fCoordTransforms.count(); }
bsalomon6251d172014-10-15 10:50:36 -0700109
110 /** Returns the coordinate transformation at index. index must be valid according to
111 numTransforms(). */
112 const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
113
joshualittabb52a12015-01-13 15:02:10 -0800114 const SkTArray<const GrCoordTransform*, true>& coordTransforms() const {
115 return fCoordTransforms;
116 }
117
wangyix4b3050b2015-08-04 07:59:37 -0700118 int numChildProcessors() const { return fChildProcessors.count(); }
119
bsalomonac856c92015-08-27 06:30:17 -0700120 const GrFragmentProcessor& childProcessor(int index) const { return *fChildProcessors[index]; }
wangyix4b3050b2015-08-04 07:59:37 -0700121
Robert Phillips9bee2e52017-05-29 12:37:20 -0400122 bool instantiate(GrResourceProvider*) const;
123
Brian Salomonaff329b2017-08-11 09:40:37 -0400124 void markPendingExecution() const;
125
joshualitt290c09b2014-12-19 13:45:20 -0800126 /** Do any of the coordtransforms for this processor require local coords? */
Brian Salomon587e08f2017-01-27 10:59:27 -0500127 bool usesLocalCoords() const { return SkToBool(fFlags & kUsesLocalCoords_Flag); }
joshualitt290c09b2014-12-19 13:45:20 -0800128
Brian Salomon587e08f2017-01-27 10:59:27 -0500129 /**
Brian Salomonf3b995b2017-02-15 10:22:23 -0500130 * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
131 * output under the following scenario:
132 * * all the color fragment processors report true to this query,
133 * * all the coverage fragment processors report true to this query,
134 * * the blend mode arithmetic allows for it it.
135 * To be compatible a fragment processor's output must be a modulation of its input color or
136 * alpha with a computed premultiplied color or alpha that is in 0..1 range. The computed color
137 * or alpha that is modulated against the input cannot depend on the input's alpha. The computed
138 * value cannot depend on the input's color channels unless it unpremultiplies the input color
139 * channels by the input alpha.
Brian Salomon587e08f2017-01-27 10:59:27 -0500140 */
Brian Salomonf3b995b2017-02-15 10:22:23 -0500141 bool compatibleWithCoverageAsAlpha() const {
142 return SkToBool(fFlags & kCompatibleWithCoverageAsAlpha_OptimizationFlag);
143 }
Brian Salomon587e08f2017-01-27 10:59:27 -0500144
145 /**
146 * If this is true then all opaque input colors to the processor produce opaque output colors.
147 */
148 bool preservesOpaqueInput() const {
149 return SkToBool(fFlags & kPreservesOpaqueInput_OptimizationFlag);
150 }
151
152 /**
153 * Tests whether given a constant input color the processor produces a constant output color
154 * (for all fragments). If true outputColor will contain the constant color produces for
155 * inputColor.
156 */
157 bool hasConstantOutputForConstantInput(GrColor4f inputColor, GrColor4f* outputColor) const {
158 if (fFlags & kConstantOutputForConstantInput_OptimizationFlag) {
159 *outputColor = this->constantOutputForConstantInput(inputColor);
160 return true;
161 }
162 return false;
163 }
164 bool hasConstantOutputForConstantInput() const {
165 return SkToBool(fFlags & kConstantOutputForConstantInput_OptimizationFlag);
166 }
dvonbeck9b03e7b2016-08-01 11:01:56 -0700167
joshualitteb2a6762014-12-04 11:35:33 -0800168 /** Returns true if this and other processor conservatively draw identically. It can only return
169 true when the two processor are of the same subclass (i.e. they return the same object from
bsalomon6251d172014-10-15 10:50:36 -0700170 from getFactory()).
171
joshualitteb2a6762014-12-04 11:35:33 -0800172 A return value of true from isEqual() should not be used to test whether the processor would
egdaniel57d3b032015-11-13 11:57:27 -0800173 generate the same shader code. To test for identical code generation use getGLSLProcessorKey
174 */
bsalomon7312ff82016-09-12 08:55:38 -0700175 bool isEqual(const GrFragmentProcessor& that) const;
bsalomon6251d172014-10-15 10:50:36 -0700176
joshualitt56995b52014-12-11 15:44:02 -0800177 /**
bsalomona624bf32016-09-20 09:12:47 -0700178 * Pre-order traversal of a FP hierarchy, or of the forest of FPs in a GrPipeline. In the latter
179 * case the tree rooted at each FP in the GrPipeline is visited successively.
bsalomonb58a2b42016-09-26 06:55:02 -0700180 */
bsalomona624bf32016-09-20 09:12:47 -0700181 class Iter : public SkNoncopyable {
182 public:
183 explicit Iter(const GrFragmentProcessor* fp) { fFPStack.push_back(fp); }
184 explicit Iter(const GrPipeline& pipeline);
185 const GrFragmentProcessor* next();
186
187 private:
188 SkSTArray<4, const GrFragmentProcessor*, true> fFPStack;
189 };
190
191 /**
bsalomonb58a2b42016-09-26 06:55:02 -0700192 * Iterates over all the Ts owned by a GrFragmentProcessor and its children or over all the Ts
193 * owned by the forest of GrFragmentProcessors in a GrPipeline. FPs are visited in the same
194 * order as Iter and each of an FP's Ts are visited in order.
bsalomona624bf32016-09-20 09:12:47 -0700195 */
bsalomonb58a2b42016-09-26 06:55:02 -0700196 template <typename T, typename BASE,
197 int (BASE::*COUNT)() const,
198 const T& (BASE::*GET)(int) const>
199 class FPItemIter : public SkNoncopyable {
bsalomona624bf32016-09-20 09:12:47 -0700200 public:
bsalomonb58a2b42016-09-26 06:55:02 -0700201 explicit FPItemIter(const GrFragmentProcessor* fp)
202 : fCurrFP(nullptr)
203 , fCTIdx(0)
204 , fFPIter(fp) {
205 fCurrFP = fFPIter.next();
206 }
207 explicit FPItemIter(const GrPipeline& pipeline)
bsalomona624bf32016-09-20 09:12:47 -0700208 : fCurrFP(nullptr)
209 , fCTIdx(0)
210 , fFPIter(pipeline) {
211 fCurrFP = fFPIter.next();
212 }
bsalomonb58a2b42016-09-26 06:55:02 -0700213
214 const T* next() {
215 if (!fCurrFP) {
216 return nullptr;
217 }
218 while (fCTIdx == (fCurrFP->*COUNT)()) {
219 fCTIdx = 0;
220 fCurrFP = fFPIter.next();
221 if (!fCurrFP) {
222 return nullptr;
223 }
224 }
225 return &(fCurrFP->*GET)(fCTIdx++);
226 }
bsalomona624bf32016-09-20 09:12:47 -0700227
228 private:
229 const GrFragmentProcessor* fCurrFP;
230 int fCTIdx;
231 GrFragmentProcessor::Iter fFPIter;
232 };
233
bsalomonb58a2b42016-09-26 06:55:02 -0700234 using CoordTransformIter = FPItemIter<GrCoordTransform,
235 GrFragmentProcessor,
236 &GrFragmentProcessor::numCoordTransforms,
237 &GrFragmentProcessor::coordTransform>;
238
Brian Salomon0bbecb22016-11-17 11:38:22 -0500239 using TextureAccessIter = FPItemIter<TextureSampler,
Brian Salomonab015ef2017-04-04 10:15:51 -0400240 GrResourceIOProcessor,
241 &GrResourceIOProcessor::numTextureSamplers,
242 &GrResourceIOProcessor::textureSampler>;
bsalomonb58a2b42016-09-26 06:55:02 -0700243
Robert Phillipsf1748f52017-09-14 14:11:24 -0400244 void visitProxies(const std::function<void(GrSurfaceProxy*)>& func) {
Robert Phillipsb493eeb2017-09-13 13:10:52 -0400245 GrFragmentProcessor::TextureAccessIter iter(this);
246 while (const GrResourceIOProcessor::TextureSampler* sampler = iter.next()) {
247 func(sampler->proxy());
248 }
249 }
250
bsalomon6251d172014-10-15 10:50:36 -0700251protected:
Brian Salomon587e08f2017-01-27 10:59:27 -0500252 enum OptimizationFlags : uint32_t {
253 kNone_OptimizationFlags,
Brian Salomonf3b995b2017-02-15 10:22:23 -0500254 kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1,
Brian Salomon587e08f2017-01-27 10:59:27 -0500255 kPreservesOpaqueInput_OptimizationFlag = 0x2,
256 kConstantOutputForConstantInput_OptimizationFlag = 0x4,
Brian Salomonf3b995b2017-02-15 10:22:23 -0500257 kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag |
Brian Salomon587e08f2017-01-27 10:59:27 -0500258 kPreservesOpaqueInput_OptimizationFlag |
259 kConstantOutputForConstantInput_OptimizationFlag
260 };
261 GR_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)
262
Brian Salomon6cd51b52017-07-26 19:07:15 -0400263 /**
264 * Can be used as a helper to decide which fragment processor OptimizationFlags should be set.
265 * This assumes that the subclass output color will be a modulation of the input color with a
266 * value read from a texture of the passed config and that the texture contains premultiplied
267 * color or alpha values that are in range.
268 */
269 static OptimizationFlags ModulateByConfigOptimizationFlags(GrPixelConfig config) {
270 if (GrPixelConfigIsOpaque(config)) {
271 return kCompatibleWithCoverageAsAlpha_OptimizationFlag |
272 kPreservesOpaqueInput_OptimizationFlag;
273 } else {
274 return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
275 }
276 }
277
Ethan Nicholasabff9562017-10-09 10:54:08 -0400278 GrFragmentProcessor(ClassID classID, OptimizationFlags optimizationFlags)
279 : INHERITED(classID)
280 , fFlags(optimizationFlags) {
Brian Salomon587e08f2017-01-27 10:59:27 -0500281 SkASSERT((fFlags & ~kAll_OptimizationFlags) == 0);
282 }
283
284 OptimizationFlags optimizationFlags() const {
285 return static_cast<OptimizationFlags>(kAll_OptimizationFlags & fFlags);
286 }
287
288 /**
289 * This allows one subclass to access another subclass's implementation of
290 * constantOutputForConstantInput. It must only be called when
291 * hasConstantOutputForConstantInput() is known to be true.
292 */
293 static GrColor4f ConstantOutputForConstantInput(const GrFragmentProcessor& fp,
294 GrColor4f input) {
295 SkASSERT(fp.hasConstantOutputForConstantInput());
296 return fp.constantOutputForConstantInput(input);
297 }
298
bsalomon6251d172014-10-15 10:50:36 -0700299 /**
300 * Fragment Processor subclasses call this from their constructor to register coordinate
bsalomonde258cd2014-10-15 19:06:21 -0700301 * transformations. Coord transforms provide a mechanism for a processor to receive coordinates
302 * in their FS code. The matrix expresses a transformation from local space. For a given
303 * fragment the matrix will be applied to the local coordinate that maps to the fragment.
304 *
305 * When the transformation has perspective, the transformed coordinates will have
mtklein790d74f2015-08-19 11:05:39 -0700306 * 3 components. Otherwise they'll have 2.
bsalomonde258cd2014-10-15 19:06:21 -0700307 *
308 * This must only be called from the constructor because GrProcessors are immutable. The
309 * processor subclass manages the lifetime of the transformations (this function only stores a
mtklein790d74f2015-08-19 11:05:39 -0700310 * pointer). The GrCoordTransform is typically a member field of the GrProcessor subclass.
bsalomonde258cd2014-10-15 19:06:21 -0700311 *
312 * A processor subclass that has multiple methods of construction should always add its coord
313 * transforms in a consistent order. The non-virtual implementation of isEqual() automatically
314 * compares transforms and will assume they line up across the two processor instances.
bsalomon6251d172014-10-15 10:50:36 -0700315 */
316 void addCoordTransform(const GrCoordTransform*);
317
318 /**
wangyix58d890b2015-08-12 09:40:47 -0700319 * FragmentProcessor subclasses call this from their constructor to register any child
wangyix93ab2542015-08-19 08:23:12 -0700320 * FragmentProcessors they have. This must be called AFTER all texture accesses and coord
321 * transforms have been added.
wangyix4b3050b2015-08-04 07:59:37 -0700322 * This is for processors whose shader code will be composed of nested processors whose output
323 * colors will be combined somehow to produce its output color. Registering these child
wangyix58d890b2015-08-12 09:40:47 -0700324 * processors will allow the ProgramBuilder to automatically handle their transformed coords and
325 * texture accesses and mangle their uniform and output color names.
wangyix4b3050b2015-08-04 07:59:37 -0700326 */
Brian Salomonaff329b2017-08-11 09:40:37 -0400327 int registerChildProcessor(std::unique_ptr<GrFragmentProcessor> child);
wangyix4b3050b2015-08-04 07:59:37 -0700328
bsalomon6251d172014-10-15 10:50:36 -0700329private:
Brian Salomon587e08f2017-01-27 10:59:27 -0500330 virtual GrColor4f constantOutputForConstantInput(GrColor4f /* inputColor */) const {
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400331 SK_ABORT("Subclass must override this if advertising this optimization.");
Brian Salomon587e08f2017-01-27 10:59:27 -0500332 return GrColor4f::TransparentBlack();
333 }
334
wangyixb1daa862015-08-18 11:29:31 -0700335 /** Returns a new instance of the appropriate *GL* implementation class
336 for the given GrFragmentProcessor; caller is responsible for deleting
337 the object. */
egdaniel57d3b032015-11-13 11:57:27 -0800338 virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const = 0;
wangyixb1daa862015-08-18 11:29:31 -0700339
wangyix4b3050b2015-08-04 07:59:37 -0700340 /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */
Brian Salomon94efbf52016-11-29 13:43:05 -0500341 virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
wangyix4b3050b2015-08-04 07:59:37 -0700342
bsalomonde258cd2014-10-15 19:06:21 -0700343 /**
344 * Subclass implements this to support isEqual(). It will only be called if it is known that
345 * the two processors are of the same subclass (i.e. they return the same object from
346 * getFactory()). The processor subclass should not compare its coord transforms as that will
347 * be performed automatically in the non-virtual isEqual().
348 */
349 virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
350
351 bool hasSameTransforms(const GrFragmentProcessor&) const;
bsalomon6251d172014-10-15 10:50:36 -0700352
Brian Salomon587e08f2017-01-27 10:59:27 -0500353 enum PrivateFlags {
354 kFirstPrivateFlag = kAll_OptimizationFlags + 1,
355 kUsesLocalCoords_Flag = kFirstPrivateFlag,
Brian Salomon587e08f2017-01-27 10:59:27 -0500356 };
357
358 mutable uint32_t fFlags = 0;
wangyix58d890b2015-08-12 09:40:47 -0700359
bsalomona624bf32016-09-20 09:12:47 -0700360 SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms;
361
Brian Salomonaff329b2017-08-11 09:40:37 -0400362 SkSTArray<1, std::unique_ptr<GrFragmentProcessor>, true> fChildProcessors;
bsalomon6251d172014-10-15 10:50:36 -0700363
Robert Phillips9bee2e52017-05-29 12:37:20 -0400364 typedef GrResourceIOProcessor INHERITED;
bsalomon6251d172014-10-15 10:50:36 -0700365};
366
Brian Salomon587e08f2017-01-27 10:59:27 -0500367GR_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)
368
bsalomon6251d172014-10-15 10:50:36 -0700369#endif