blob: 49ccceabae60289cb8c9e74cca5c8b15735a3e7c [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 /**
38 * Similar to the above but it modulates the output r,g,b of the child processor by the input
39 * rgb and then multiplies all the components by the input alpha. This effectively modulates
40 * the child processor's premul color by a unpremul'ed input and produces a premul output
41 */
bungeman06ca8ec2016-06-09 08:01:03 -070042 static sk_sp<GrFragmentProcessor> MulOutputByInputUnpremulColor(sk_sp<GrFragmentProcessor>);
bsalomonf1b7a1d2015-09-28 06:26:28 -070043
44 /**
bsalomone25eea42015-09-29 06:38:55 -070045 * Returns a parent fragment processor that adopts the passed fragment processor as a child.
46 * The parent will ignore its input color and instead feed the passed in color as input to the
47 * child.
bsalomonf1b7a1d2015-09-28 06:26:28 -070048 */
brianosman4cea3b92016-09-08 09:33:50 -070049 static sk_sp<GrFragmentProcessor> OverrideInput(sk_sp<GrFragmentProcessor>, GrColor4f);
bsalomon87ba62e2015-09-22 06:41:59 -070050
bsalomone25eea42015-09-29 06:38:55 -070051 /**
dvonbeckc526da92016-07-20 11:20:30 -070052 * Returns a fragment processor that premuls the input before calling the passed in fragment
53 * processor.
54 */
55 static sk_sp<GrFragmentProcessor> PremulInput(sk_sp<GrFragmentProcessor>);
56
57 /**
bsalomone25eea42015-09-29 06:38:55 -070058 * Returns a fragment processor that runs the passed in array of fragment processors in a
59 * series. The original input is passed to the first, the first's output is passed to the
60 * second, etc. The output of the returned processor is the output of the last processor of the
61 * series.
bungeman06ca8ec2016-06-09 08:01:03 -070062 *
63 * The array elements with be moved.
bsalomone25eea42015-09-29 06:38:55 -070064 */
bungeman06ca8ec2016-06-09 08:01:03 -070065 static sk_sp<GrFragmentProcessor> RunInSeries(sk_sp<GrFragmentProcessor>*, int cnt);
bsalomone25eea42015-09-29 06:38:55 -070066
bsalomon6251d172014-10-15 10:50:36 -070067 GrFragmentProcessor()
68 : INHERITED()
dvonbeck9b03e7b2016-08-01 11:01:56 -070069 , fUsesDistanceVectorField(false)
bsalomonb58a2b42016-09-26 06:55:02 -070070 , fUsesLocalCoords(false) {}
bsalomon6251d172014-10-15 10:50:36 -070071
bsalomonac856c92015-08-27 06:30:17 -070072 ~GrFragmentProcessor() override;
73
egdaniel57d3b032015-11-13 11:57:27 -080074 GrGLSLFragmentProcessor* createGLSLInstance() const;
joshualitteb2a6762014-12-04 11:35:33 -080075
Brian Salomon94efbf52016-11-29 13:43:05 -050076 void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
egdaniel57d3b032015-11-13 11:57:27 -080077 this->onGetGLSLProcessorKey(caps, b);
wangyix4b3050b2015-08-04 07:59:37 -070078 for (int i = 0; i < fChildProcessors.count(); ++i) {
egdaniel57d3b032015-11-13 11:57:27 -080079 fChildProcessors[i]->getGLSLProcessorKey(caps, b);
wangyix4b3050b2015-08-04 07:59:37 -070080 }
81 }
82
bsalomona624bf32016-09-20 09:12:47 -070083 int numCoordTransforms() const { return fCoordTransforms.count(); }
bsalomon6251d172014-10-15 10:50:36 -070084
85 /** Returns the coordinate transformation at index. index must be valid according to
86 numTransforms(). */
87 const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
88
joshualittabb52a12015-01-13 15:02:10 -080089 const SkTArray<const GrCoordTransform*, true>& coordTransforms() const {
90 return fCoordTransforms;
91 }
92
wangyix4b3050b2015-08-04 07:59:37 -070093 int numChildProcessors() const { return fChildProcessors.count(); }
94
bsalomonac856c92015-08-27 06:30:17 -070095 const GrFragmentProcessor& childProcessor(int index) const { return *fChildProcessors[index]; }
wangyix4b3050b2015-08-04 07:59:37 -070096
joshualitt290c09b2014-12-19 13:45:20 -080097 /** Do any of the coordtransforms for this processor require local coords? */
98 bool usesLocalCoords() const { return fUsesLocalCoords; }
99
dvonbeck9b03e7b2016-08-01 11:01:56 -0700100 /** Does this FP need a vector to the nearest edge? */
101 bool usesDistanceVectorField() const { return fUsesDistanceVectorField; }
102
joshualitteb2a6762014-12-04 11:35:33 -0800103 /** Returns true if this and other processor conservatively draw identically. It can only return
104 true when the two processor are of the same subclass (i.e. they return the same object from
bsalomon6251d172014-10-15 10:50:36 -0700105 from getFactory()).
106
joshualitteb2a6762014-12-04 11:35:33 -0800107 A return value of true from isEqual() should not be used to test whether the processor would
egdaniel57d3b032015-11-13 11:57:27 -0800108 generate the same shader code. To test for identical code generation use getGLSLProcessorKey
109 */
bsalomon7312ff82016-09-12 08:55:38 -0700110 bool isEqual(const GrFragmentProcessor& that) const;
bsalomon6251d172014-10-15 10:50:36 -0700111
joshualitt56995b52014-12-11 15:44:02 -0800112 /**
113 * This function is used to perform optimizations. When called the invarientOuput param
114 * indicate whether the input components to this processor in the FS will have known values.
115 * In inout the validFlags member is a bitfield of GrColorComponentFlags. The isSingleComponent
116 * member indicates whether the input will be 1 or 4 bytes. The function updates the members of
117 * inout to indicate known values of its output. A component of the color member only has
118 * meaning if the corresponding bit in validFlags is set.
119 */
bsalomonc21b09e2015-08-28 18:46:56 -0700120 void computeInvariantOutput(GrInvariantOutput* inout) const {
121 this->onComputeInvariantOutput(inout);
122 }
joshualitt56995b52014-12-11 15:44:02 -0800123
bsalomona624bf32016-09-20 09:12:47 -0700124 /**
125 * Pre-order traversal of a FP hierarchy, or of the forest of FPs in a GrPipeline. In the latter
126 * case the tree rooted at each FP in the GrPipeline is visited successively.
bsalomonb58a2b42016-09-26 06:55:02 -0700127 */
bsalomona624bf32016-09-20 09:12:47 -0700128 class Iter : public SkNoncopyable {
129 public:
130 explicit Iter(const GrFragmentProcessor* fp) { fFPStack.push_back(fp); }
131 explicit Iter(const GrPipeline& pipeline);
132 const GrFragmentProcessor* next();
133
134 private:
135 SkSTArray<4, const GrFragmentProcessor*, true> fFPStack;
136 };
137
138 /**
bsalomonb58a2b42016-09-26 06:55:02 -0700139 * Iterates over all the Ts owned by a GrFragmentProcessor and its children or over all the Ts
140 * owned by the forest of GrFragmentProcessors in a GrPipeline. FPs are visited in the same
141 * order as Iter and each of an FP's Ts are visited in order.
bsalomona624bf32016-09-20 09:12:47 -0700142 */
bsalomonb58a2b42016-09-26 06:55:02 -0700143 template <typename T, typename BASE,
144 int (BASE::*COUNT)() const,
145 const T& (BASE::*GET)(int) const>
146 class FPItemIter : public SkNoncopyable {
bsalomona624bf32016-09-20 09:12:47 -0700147 public:
bsalomonb58a2b42016-09-26 06:55:02 -0700148 explicit FPItemIter(const GrFragmentProcessor* fp)
149 : fCurrFP(nullptr)
150 , fCTIdx(0)
151 , fFPIter(fp) {
152 fCurrFP = fFPIter.next();
153 }
154 explicit FPItemIter(const GrPipeline& pipeline)
bsalomona624bf32016-09-20 09:12:47 -0700155 : fCurrFP(nullptr)
156 , fCTIdx(0)
157 , fFPIter(pipeline) {
158 fCurrFP = fFPIter.next();
159 }
bsalomonb58a2b42016-09-26 06:55:02 -0700160
161 const T* next() {
162 if (!fCurrFP) {
163 return nullptr;
164 }
165 while (fCTIdx == (fCurrFP->*COUNT)()) {
166 fCTIdx = 0;
167 fCurrFP = fFPIter.next();
168 if (!fCurrFP) {
169 return nullptr;
170 }
171 }
172 return &(fCurrFP->*GET)(fCTIdx++);
173 }
bsalomona624bf32016-09-20 09:12:47 -0700174
175 private:
176 const GrFragmentProcessor* fCurrFP;
177 int fCTIdx;
178 GrFragmentProcessor::Iter fFPIter;
179 };
180
bsalomonb58a2b42016-09-26 06:55:02 -0700181 using CoordTransformIter = FPItemIter<GrCoordTransform,
182 GrFragmentProcessor,
183 &GrFragmentProcessor::numCoordTransforms,
184 &GrFragmentProcessor::coordTransform>;
185
Brian Salomon0bbecb22016-11-17 11:38:22 -0500186 using TextureAccessIter = FPItemIter<TextureSampler,
bsalomonb58a2b42016-09-26 06:55:02 -0700187 GrProcessor,
Brian Salomon0bbecb22016-11-17 11:38:22 -0500188 &GrProcessor::numTextureSamplers,
189 &GrProcessor::textureSampler>;
bsalomonb58a2b42016-09-26 06:55:02 -0700190
bsalomon6251d172014-10-15 10:50:36 -0700191protected:
192 /**
193 * Fragment Processor subclasses call this from their constructor to register coordinate
bsalomonde258cd2014-10-15 19:06:21 -0700194 * transformations. Coord transforms provide a mechanism for a processor to receive coordinates
195 * in their FS code. The matrix expresses a transformation from local space. For a given
196 * fragment the matrix will be applied to the local coordinate that maps to the fragment.
197 *
198 * When the transformation has perspective, the transformed coordinates will have
mtklein790d74f2015-08-19 11:05:39 -0700199 * 3 components. Otherwise they'll have 2.
bsalomonde258cd2014-10-15 19:06:21 -0700200 *
201 * This must only be called from the constructor because GrProcessors are immutable. The
202 * processor subclass manages the lifetime of the transformations (this function only stores a
mtklein790d74f2015-08-19 11:05:39 -0700203 * pointer). The GrCoordTransform is typically a member field of the GrProcessor subclass.
bsalomonde258cd2014-10-15 19:06:21 -0700204 *
205 * A processor subclass that has multiple methods of construction should always add its coord
206 * transforms in a consistent order. The non-virtual implementation of isEqual() automatically
207 * compares transforms and will assume they line up across the two processor instances.
bsalomon6251d172014-10-15 10:50:36 -0700208 */
209 void addCoordTransform(const GrCoordTransform*);
210
211 /**
wangyix58d890b2015-08-12 09:40:47 -0700212 * FragmentProcessor subclasses call this from their constructor to register any child
wangyix93ab2542015-08-19 08:23:12 -0700213 * FragmentProcessors they have. This must be called AFTER all texture accesses and coord
214 * transforms have been added.
wangyix4b3050b2015-08-04 07:59:37 -0700215 * This is for processors whose shader code will be composed of nested processors whose output
216 * colors will be combined somehow to produce its output color. Registering these child
wangyix58d890b2015-08-12 09:40:47 -0700217 * processors will allow the ProgramBuilder to automatically handle their transformed coords and
218 * texture accesses and mangle their uniform and output color names.
wangyix4b3050b2015-08-04 07:59:37 -0700219 */
bungeman06ca8ec2016-06-09 08:01:03 -0700220 int registerChildProcessor(sk_sp<GrFragmentProcessor> child);
wangyix4b3050b2015-08-04 07:59:37 -0700221
222 /**
joshualitt56995b52014-12-11 15:44:02 -0800223 * Subclass implements this to support getConstantColorComponents(...).
wangyix54017d72015-08-18 07:39:33 -0700224 *
225 * Note: it's up to the subclass implementation to do any recursive call to compute the child
226 * procs' output invariants; computeInvariantOutput will not be recursive.
joshualitt56995b52014-12-11 15:44:02 -0800227 */
228 virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const = 0;
229
dvonbeck9b03e7b2016-08-01 11:01:56 -0700230 /* Sub-classes should set this to true in their constructors if they need access to a distance
231 * vector field to the nearest edge
232 */
233 bool fUsesDistanceVectorField;
234
bsalomon6251d172014-10-15 10:50:36 -0700235private:
bsalomon42048002015-08-27 16:43:48 -0700236 void notifyRefCntIsZero() const final;
237
wangyixb1daa862015-08-18 11:29:31 -0700238 /** Returns a new instance of the appropriate *GL* implementation class
239 for the given GrFragmentProcessor; caller is responsible for deleting
240 the object. */
egdaniel57d3b032015-11-13 11:57:27 -0800241 virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const = 0;
wangyixb1daa862015-08-18 11:29:31 -0700242
wangyix4b3050b2015-08-04 07:59:37 -0700243 /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */
Brian Salomon94efbf52016-11-29 13:43:05 -0500244 virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
wangyix4b3050b2015-08-04 07:59:37 -0700245
bsalomonde258cd2014-10-15 19:06:21 -0700246 /**
247 * Subclass implements this to support isEqual(). It will only be called if it is known that
248 * the two processors are of the same subclass (i.e. they return the same object from
249 * getFactory()). The processor subclass should not compare its coord transforms as that will
250 * be performed automatically in the non-virtual isEqual().
251 */
252 virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
253
254 bool hasSameTransforms(const GrFragmentProcessor&) const;
bsalomon6251d172014-10-15 10:50:36 -0700255
bungeman06ca8ec2016-06-09 08:01:03 -0700256 bool fUsesLocalCoords;
wangyix58d890b2015-08-12 09:40:47 -0700257
bsalomona624bf32016-09-20 09:12:47 -0700258 SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms;
259
wangyix58d890b2015-08-12 09:40:47 -0700260 /**
bungeman06ca8ec2016-06-09 08:01:03 -0700261 * This is not SkSTArray<1, sk_sp<GrFragmentProcessor>> because this class holds strong
262 * references until notifyRefCntIsZero and then it holds pending executions.
263 */
264 SkSTArray<1, GrFragmentProcessor*, true> fChildProcessors;
bsalomon6251d172014-10-15 10:50:36 -0700265
266 typedef GrProcessor INHERITED;
267};
268
bsalomon6251d172014-10-15 10:50:36 -0700269#endif