blob: f82146de659273de342cc31ec5627230ede9edfc [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"
Brian Salomonee783962018-08-01 09:55:10 -040012#include "GrProxyRef.h"
Brian Osman1d5b5982018-10-01 13:41:39 -040013#include "SkPM4f.h"
bsalomon6251d172014-10-15 10:50:36 -070014
15class GrCoordTransform;
egdaniel64c47282015-11-13 06:54:19 -080016class GrGLSLFragmentProcessor;
Chris Dalton1c548942018-05-22 13:09:48 -060017class GrPaint;
bsalomona624bf32016-09-20 09:12:47 -070018class GrPipeline;
joshualitteb2a6762014-12-04 11:35:33 -080019class GrProcessorKeyBuilder;
Brian Salomon94efbf52016-11-29 13:43:05 -050020class GrShaderCaps;
Brian Osmance425512017-03-22 14:37:50 -040021class GrSwizzle;
bsalomon6251d172014-10-15 10:50:36 -070022
Ethan Nicholasf7b88202017-09-18 14:10:39 -040023/** Provides custom fragment shader code. Fragment processors receive an input color (half4) and
bsalomon6251d172014-10-15 10:50:36 -070024 produce an output color. They may reference textures and uniforms. They may use
25 GrCoordTransforms to receive a transformation of the local coordinates that map from local space
26 to the fragment being processed.
27 */
Brian Salomone782f842018-07-31 13:53:11 -040028class GrFragmentProcessor : public GrProcessor {
bsalomon6251d172014-10-15 10:50:36 -070029public:
Brian Salomone782f842018-07-31 13:53:11 -040030 class TextureSampler;
31
bsalomon87ba62e2015-09-22 06:41:59 -070032 /**
33 * In many instances (e.g. SkShader::asFragmentProcessor() implementations) it is desirable to
34 * only consider the input color's alpha. However, there is a competing desire to have reusable
35 * GrFragmentProcessor subclasses that can be used in other scenarios where the entire input
36 * color is considered. This function exists to filter the input color and pass it to a FP. It
37 * does so by returning a parent FP that multiplies the passed in FPs output by the parent's
38 * input alpha. The passed in FP will not receive an input color.
39 */
Mike Reed28eaed22018-02-01 11:24:53 -050040 static std::unique_ptr<GrFragmentProcessor> MulChildByInputAlpha(
41 std::unique_ptr<GrFragmentProcessor> child);
42
43 /**
44 * Like MulChildByInputAlpha(), but reverses the sense of src and dst. In this case, return
45 * the input modulated by the child's alpha. The passed in FP will not receive an input color.
46 *
47 * output = input * child.a
48 */
49 static std::unique_ptr<GrFragmentProcessor> MulInputByChildAlpha(
50 std::unique_ptr<GrFragmentProcessor> child);
bsalomonf1b7a1d2015-09-28 06:26:28 -070051
52 /**
Brian Salomon22af73f2017-01-26 11:25:12 -050053 * This assumes that the input color to the returned processor will be unpremul and that the
54 * passed processor (which becomes the returned processor's child) produces a premul output.
55 * The result of the returned processor is a premul of its input color modulated by the child
56 * processor's premul output.
bsalomonf1b7a1d2015-09-28 06:26:28 -070057 */
Brian Salomonaff329b2017-08-11 09:40:37 -040058 static std::unique_ptr<GrFragmentProcessor> MakeInputPremulAndMulByOutput(
59 std::unique_ptr<GrFragmentProcessor>);
bsalomonf1b7a1d2015-09-28 06:26:28 -070060
61 /**
bsalomone25eea42015-09-29 06:38:55 -070062 * Returns a parent fragment processor that adopts the passed fragment processor as a child.
63 * The parent will ignore its input color and instead feed the passed in color as input to the
64 * child.
bsalomonf1b7a1d2015-09-28 06:26:28 -070065 */
Brian Salomonaff329b2017-08-11 09:40:37 -040066 static std::unique_ptr<GrFragmentProcessor> OverrideInput(std::unique_ptr<GrFragmentProcessor>,
67 GrColor4f);
bsalomon87ba62e2015-09-22 06:41:59 -070068
bsalomone25eea42015-09-29 06:38:55 -070069 /**
dvonbeckc526da92016-07-20 11:20:30 -070070 * Returns a fragment processor that premuls the input before calling the passed in fragment
71 * processor.
72 */
Brian Salomonaff329b2017-08-11 09:40:37 -040073 static std::unique_ptr<GrFragmentProcessor> PremulInput(std::unique_ptr<GrFragmentProcessor>);
dvonbeckc526da92016-07-20 11:20:30 -070074
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
Brian Salomone782f842018-07-31 13:53:11 -0400108 int numTextureSamplers() const { return fTextureSamplerCnt; }
109 const TextureSampler& textureSampler(int i) const;
110
bsalomona624bf32016-09-20 09:12:47 -0700111 int numCoordTransforms() const { return fCoordTransforms.count(); }
bsalomon6251d172014-10-15 10:50:36 -0700112
113 /** Returns the coordinate transformation at index. index must be valid according to
114 numTransforms(). */
115 const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
116
joshualittabb52a12015-01-13 15:02:10 -0800117 const SkTArray<const GrCoordTransform*, true>& coordTransforms() const {
118 return fCoordTransforms;
119 }
120
wangyix4b3050b2015-08-04 07:59:37 -0700121 int numChildProcessors() const { return fChildProcessors.count(); }
122
bsalomonac856c92015-08-27 06:30:17 -0700123 const GrFragmentProcessor& childProcessor(int index) const { return *fChildProcessors[index]; }
wangyix4b3050b2015-08-04 07:59:37 -0700124
Robert Phillips9bee2e52017-05-29 12:37:20 -0400125 bool instantiate(GrResourceProvider*) const;
126
Brian Salomonaff329b2017-08-11 09:40:37 -0400127 void markPendingExecution() const;
128
joshualitt290c09b2014-12-19 13:45:20 -0800129 /** Do any of the coordtransforms for this processor require local coords? */
Brian Salomon587e08f2017-01-27 10:59:27 -0500130 bool usesLocalCoords() const { return SkToBool(fFlags & kUsesLocalCoords_Flag); }
joshualitt290c09b2014-12-19 13:45:20 -0800131
Brian Salomon587e08f2017-01-27 10:59:27 -0500132 /**
Brian Salomonf3b995b2017-02-15 10:22:23 -0500133 * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
134 * output under the following scenario:
135 * * all the color fragment processors report true to this query,
136 * * all the coverage fragment processors report true to this query,
137 * * the blend mode arithmetic allows for it it.
138 * To be compatible a fragment processor's output must be a modulation of its input color or
139 * alpha with a computed premultiplied color or alpha that is in 0..1 range. The computed color
140 * or alpha that is modulated against the input cannot depend on the input's alpha. The computed
141 * value cannot depend on the input's color channels unless it unpremultiplies the input color
142 * channels by the input alpha.
Brian Salomon587e08f2017-01-27 10:59:27 -0500143 */
Brian Salomonf3b995b2017-02-15 10:22:23 -0500144 bool compatibleWithCoverageAsAlpha() const {
145 return SkToBool(fFlags & kCompatibleWithCoverageAsAlpha_OptimizationFlag);
146 }
Brian Salomon587e08f2017-01-27 10:59:27 -0500147
148 /**
149 * If this is true then all opaque input colors to the processor produce opaque output colors.
150 */
151 bool preservesOpaqueInput() const {
152 return SkToBool(fFlags & kPreservesOpaqueInput_OptimizationFlag);
153 }
154
155 /**
156 * Tests whether given a constant input color the processor produces a constant output color
157 * (for all fragments). If true outputColor will contain the constant color produces for
158 * inputColor.
159 */
Brian Osman1d5b5982018-10-01 13:41:39 -0400160 bool hasConstantOutputForConstantInput(SkPMColor4f inputColor, SkPMColor4f* outputColor) const {
Brian Salomon587e08f2017-01-27 10:59:27 -0500161 if (fFlags & kConstantOutputForConstantInput_OptimizationFlag) {
162 *outputColor = this->constantOutputForConstantInput(inputColor);
163 return true;
164 }
165 return false;
166 }
167 bool hasConstantOutputForConstantInput() const {
168 return SkToBool(fFlags & kConstantOutputForConstantInput_OptimizationFlag);
169 }
dvonbeck9b03e7b2016-08-01 11:01:56 -0700170
joshualitteb2a6762014-12-04 11:35:33 -0800171 /** Returns true if this and other processor conservatively draw identically. It can only return
172 true when the two processor are of the same subclass (i.e. they return the same object from
bsalomon6251d172014-10-15 10:50:36 -0700173 from getFactory()).
174
joshualitteb2a6762014-12-04 11:35:33 -0800175 A return value of true from isEqual() should not be used to test whether the processor would
egdaniel57d3b032015-11-13 11:57:27 -0800176 generate the same shader code. To test for identical code generation use getGLSLProcessorKey
177 */
bsalomon7312ff82016-09-12 08:55:38 -0700178 bool isEqual(const GrFragmentProcessor& that) const;
bsalomon6251d172014-10-15 10:50:36 -0700179
joshualitt56995b52014-12-11 15:44:02 -0800180 /**
bsalomona624bf32016-09-20 09:12:47 -0700181 * Pre-order traversal of a FP hierarchy, or of the forest of FPs in a GrPipeline. In the latter
182 * case the tree rooted at each FP in the GrPipeline is visited successively.
bsalomonb58a2b42016-09-26 06:55:02 -0700183 */
bsalomona624bf32016-09-20 09:12:47 -0700184 class Iter : public SkNoncopyable {
185 public:
186 explicit Iter(const GrFragmentProcessor* fp) { fFPStack.push_back(fp); }
187 explicit Iter(const GrPipeline& pipeline);
Chris Dalton1c548942018-05-22 13:09:48 -0600188 explicit Iter(const GrPaint&);
bsalomona624bf32016-09-20 09:12:47 -0700189 const GrFragmentProcessor* next();
190
191 private:
192 SkSTArray<4, const GrFragmentProcessor*, true> fFPStack;
193 };
194
195 /**
bsalomonb58a2b42016-09-26 06:55:02 -0700196 * Iterates over all the Ts owned by a GrFragmentProcessor and its children or over all the Ts
197 * owned by the forest of GrFragmentProcessors in a GrPipeline. FPs are visited in the same
198 * order as Iter and each of an FP's Ts are visited in order.
bsalomona624bf32016-09-20 09:12:47 -0700199 */
Brian Salomone782f842018-07-31 13:53:11 -0400200 template <typename T, int (GrFragmentProcessor::*COUNT)() const,
201 const T& (GrFragmentProcessor::*GET)(int)const>
bsalomonb58a2b42016-09-26 06:55:02 -0700202 class FPItemIter : public SkNoncopyable {
bsalomona624bf32016-09-20 09:12:47 -0700203 public:
bsalomonb58a2b42016-09-26 06:55:02 -0700204 explicit FPItemIter(const GrFragmentProcessor* fp)
205 : fCurrFP(nullptr)
206 , fCTIdx(0)
207 , fFPIter(fp) {
208 fCurrFP = fFPIter.next();
209 }
210 explicit FPItemIter(const GrPipeline& pipeline)
bsalomona624bf32016-09-20 09:12:47 -0700211 : fCurrFP(nullptr)
212 , fCTIdx(0)
213 , fFPIter(pipeline) {
214 fCurrFP = fFPIter.next();
215 }
bsalomonb58a2b42016-09-26 06:55:02 -0700216
217 const T* next() {
218 if (!fCurrFP) {
219 return nullptr;
220 }
221 while (fCTIdx == (fCurrFP->*COUNT)()) {
222 fCTIdx = 0;
223 fCurrFP = fFPIter.next();
224 if (!fCurrFP) {
225 return nullptr;
226 }
227 }
228 return &(fCurrFP->*GET)(fCTIdx++);
229 }
bsalomona624bf32016-09-20 09:12:47 -0700230
231 private:
232 const GrFragmentProcessor* fCurrFP;
233 int fCTIdx;
234 GrFragmentProcessor::Iter fFPIter;
235 };
236
bsalomonb58a2b42016-09-26 06:55:02 -0700237 using CoordTransformIter = FPItemIter<GrCoordTransform,
bsalomonb58a2b42016-09-26 06:55:02 -0700238 &GrFragmentProcessor::numCoordTransforms,
239 &GrFragmentProcessor::coordTransform>;
240
Brian Salomon0bbecb22016-11-17 11:38:22 -0500241 using TextureAccessIter = FPItemIter<TextureSampler,
Brian Salomone782f842018-07-31 13:53:11 -0400242 &GrFragmentProcessor::numTextureSamplers,
243 &GrFragmentProcessor::textureSampler>;
bsalomonb58a2b42016-09-26 06:55:02 -0700244
Brian Salomone782f842018-07-31 13:53:11 -0400245 void visitProxies(const std::function<void(GrSurfaceProxy*)>& func);
Robert Phillipsb493eeb2017-09-13 13:10:52 -0400246
bsalomon6251d172014-10-15 10:50:36 -0700247protected:
Brian Salomon587e08f2017-01-27 10:59:27 -0500248 enum OptimizationFlags : uint32_t {
249 kNone_OptimizationFlags,
Brian Salomonf3b995b2017-02-15 10:22:23 -0500250 kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1,
Brian Salomon587e08f2017-01-27 10:59:27 -0500251 kPreservesOpaqueInput_OptimizationFlag = 0x2,
252 kConstantOutputForConstantInput_OptimizationFlag = 0x4,
Brian Salomonf3b995b2017-02-15 10:22:23 -0500253 kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag |
Brian Salomon587e08f2017-01-27 10:59:27 -0500254 kPreservesOpaqueInput_OptimizationFlag |
255 kConstantOutputForConstantInput_OptimizationFlag
256 };
257 GR_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags)
258
Brian Salomon6cd51b52017-07-26 19:07:15 -0400259 /**
260 * Can be used as a helper to decide which fragment processor OptimizationFlags should be set.
261 * This assumes that the subclass output color will be a modulation of the input color with a
262 * value read from a texture of the passed config and that the texture contains premultiplied
263 * color or alpha values that are in range.
264 */
265 static OptimizationFlags ModulateByConfigOptimizationFlags(GrPixelConfig config) {
266 if (GrPixelConfigIsOpaque(config)) {
267 return kCompatibleWithCoverageAsAlpha_OptimizationFlag |
268 kPreservesOpaqueInput_OptimizationFlag;
269 } else {
270 return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
271 }
272 }
273
Ethan Nicholasabff9562017-10-09 10:54:08 -0400274 GrFragmentProcessor(ClassID classID, OptimizationFlags optimizationFlags)
275 : INHERITED(classID)
276 , fFlags(optimizationFlags) {
Brian Salomon587e08f2017-01-27 10:59:27 -0500277 SkASSERT((fFlags & ~kAll_OptimizationFlags) == 0);
278 }
279
280 OptimizationFlags optimizationFlags() const {
281 return static_cast<OptimizationFlags>(kAll_OptimizationFlags & fFlags);
282 }
283
284 /**
285 * This allows one subclass to access another subclass's implementation of
286 * constantOutputForConstantInput. It must only be called when
287 * hasConstantOutputForConstantInput() is known to be true.
288 */
Brian Osman1d5b5982018-10-01 13:41:39 -0400289 static SkPMColor4f ConstantOutputForConstantInput(const GrFragmentProcessor& fp,
290 const SkPMColor4f& input) {
Brian Salomon587e08f2017-01-27 10:59:27 -0500291 SkASSERT(fp.hasConstantOutputForConstantInput());
292 return fp.constantOutputForConstantInput(input);
293 }
294
bsalomon6251d172014-10-15 10:50:36 -0700295 /**
296 * Fragment Processor subclasses call this from their constructor to register coordinate
bsalomonde258cd2014-10-15 19:06:21 -0700297 * transformations. Coord transforms provide a mechanism for a processor to receive coordinates
298 * in their FS code. The matrix expresses a transformation from local space. For a given
299 * fragment the matrix will be applied to the local coordinate that maps to the fragment.
300 *
301 * When the transformation has perspective, the transformed coordinates will have
mtklein790d74f2015-08-19 11:05:39 -0700302 * 3 components. Otherwise they'll have 2.
bsalomonde258cd2014-10-15 19:06:21 -0700303 *
304 * This must only be called from the constructor because GrProcessors are immutable. The
305 * processor subclass manages the lifetime of the transformations (this function only stores a
mtklein790d74f2015-08-19 11:05:39 -0700306 * pointer). The GrCoordTransform is typically a member field of the GrProcessor subclass.
bsalomonde258cd2014-10-15 19:06:21 -0700307 *
308 * A processor subclass that has multiple methods of construction should always add its coord
309 * transforms in a consistent order. The non-virtual implementation of isEqual() automatically
310 * compares transforms and will assume they line up across the two processor instances.
bsalomon6251d172014-10-15 10:50:36 -0700311 */
312 void addCoordTransform(const GrCoordTransform*);
313
314 /**
wangyix58d890b2015-08-12 09:40:47 -0700315 * FragmentProcessor subclasses call this from their constructor to register any child
wangyix93ab2542015-08-19 08:23:12 -0700316 * FragmentProcessors they have. This must be called AFTER all texture accesses and coord
317 * transforms have been added.
wangyix4b3050b2015-08-04 07:59:37 -0700318 * This is for processors whose shader code will be composed of nested processors whose output
319 * colors will be combined somehow to produce its output color. Registering these child
wangyix58d890b2015-08-12 09:40:47 -0700320 * processors will allow the ProgramBuilder to automatically handle their transformed coords and
321 * texture accesses and mangle their uniform and output color names.
wangyix4b3050b2015-08-04 07:59:37 -0700322 */
Brian Salomonaff329b2017-08-11 09:40:37 -0400323 int registerChildProcessor(std::unique_ptr<GrFragmentProcessor> child);
wangyix4b3050b2015-08-04 07:59:37 -0700324
Brian Salomone782f842018-07-31 13:53:11 -0400325 void setTextureSamplerCnt(int cnt) {
326 SkASSERT(cnt >= 0);
327 fTextureSamplerCnt = cnt;
328 }
329
330 /**
331 * Helper for implementing onTextureSampler(). E.g.:
332 * return IthTexureSampler(i, fMyFirstSampler, fMySecondSampler, fMyThirdSampler);
333 */
334 template <typename... Args>
335 static const TextureSampler& IthTextureSampler(int i, const TextureSampler& samp0,
336 const Args&... samps) {
337 return (0 == i) ? samp0 : IthTextureSampler(i - 1, samps...);
338 }
339 inline static const TextureSampler& IthTextureSampler(int i);
340
bsalomon6251d172014-10-15 10:50:36 -0700341private:
Brian Osman1d5b5982018-10-01 13:41:39 -0400342 virtual SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& /* inputColor */) const {
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400343 SK_ABORT("Subclass must override this if advertising this optimization.");
Brian Osman1d5b5982018-10-01 13:41:39 -0400344 return { 0, 0, 0, 0 };
Brian Salomon587e08f2017-01-27 10:59:27 -0500345 }
346
wangyixb1daa862015-08-18 11:29:31 -0700347 /** Returns a new instance of the appropriate *GL* implementation class
348 for the given GrFragmentProcessor; caller is responsible for deleting
349 the object. */
egdaniel57d3b032015-11-13 11:57:27 -0800350 virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const = 0;
wangyixb1daa862015-08-18 11:29:31 -0700351
wangyix4b3050b2015-08-04 07:59:37 -0700352 /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */
Brian Salomon94efbf52016-11-29 13:43:05 -0500353 virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;
wangyix4b3050b2015-08-04 07:59:37 -0700354
bsalomonde258cd2014-10-15 19:06:21 -0700355 /**
356 * Subclass implements this to support isEqual(). It will only be called if it is known that
357 * the two processors are of the same subclass (i.e. they return the same object from
358 * getFactory()). The processor subclass should not compare its coord transforms as that will
359 * be performed automatically in the non-virtual isEqual().
360 */
361 virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
362
Brian Salomone782f842018-07-31 13:53:11 -0400363 virtual const TextureSampler& onTextureSampler(int) const { return IthTextureSampler(0); }
364
bsalomonde258cd2014-10-15 19:06:21 -0700365 bool hasSameTransforms(const GrFragmentProcessor&) const;
bsalomon6251d172014-10-15 10:50:36 -0700366
Brian Salomon587e08f2017-01-27 10:59:27 -0500367 enum PrivateFlags {
368 kFirstPrivateFlag = kAll_OptimizationFlags + 1,
369 kUsesLocalCoords_Flag = kFirstPrivateFlag,
Brian Salomon587e08f2017-01-27 10:59:27 -0500370 };
371
372 mutable uint32_t fFlags = 0;
wangyix58d890b2015-08-12 09:40:47 -0700373
Brian Salomone782f842018-07-31 13:53:11 -0400374 int fTextureSamplerCnt = 0;
375
bsalomona624bf32016-09-20 09:12:47 -0700376 SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms;
377
Brian Salomonaff329b2017-08-11 09:40:37 -0400378 SkSTArray<1, std::unique_ptr<GrFragmentProcessor>, true> fChildProcessors;
bsalomon6251d172014-10-15 10:50:36 -0700379
Brian Salomone782f842018-07-31 13:53:11 -0400380 typedef GrProcessor INHERITED;
bsalomon6251d172014-10-15 10:50:36 -0700381};
382
Brian Salomone782f842018-07-31 13:53:11 -0400383/**
384 * Used to represent a texture that is required by a GrFragmentProcessor. It holds a GrTextureProxy
385 * along with an associated GrSamplerState. TextureSamplers don't perform any coord manipulation to
386 * account for texture origin.
387 */
388class GrFragmentProcessor::TextureSampler {
389public:
390 TextureSampler() = default;
391
392 /**
393 * This copy constructor is used by GrFragmentProcessor::clone() implementations. The copy
394 * always takes a new ref on the texture proxy as the new fragment processor will not yet be
395 * in pending execution state.
396 */
397 explicit TextureSampler(const TextureSampler& that)
398 : fProxyRef(sk_ref_sp(that.fProxyRef.get()), that.fProxyRef.ioType())
399 , fSamplerState(that.fSamplerState) {}
400
401 TextureSampler(sk_sp<GrTextureProxy>, const GrSamplerState&);
402
403 explicit TextureSampler(sk_sp<GrTextureProxy>,
404 GrSamplerState::Filter = GrSamplerState::Filter::kNearest,
405 GrSamplerState::WrapMode wrapXAndY = GrSamplerState::WrapMode::kClamp);
406
407 TextureSampler& operator=(const TextureSampler&) = delete;
408
409 void reset(sk_sp<GrTextureProxy>, const GrSamplerState&);
410 void reset(sk_sp<GrTextureProxy>,
411 GrSamplerState::Filter = GrSamplerState::Filter::kNearest,
412 GrSamplerState::WrapMode wrapXAndY = GrSamplerState::WrapMode::kClamp);
413
414 bool operator==(const TextureSampler& that) const {
415 return this->proxy()->underlyingUniqueID() == that.proxy()->underlyingUniqueID() &&
416 fSamplerState == that.fSamplerState;
417 }
418
419 bool operator!=(const TextureSampler& other) const { return !(*this == other); }
420
421 // 'instantiate' should only ever be called at flush time.
422 bool instantiate(GrResourceProvider* resourceProvider) const {
423 return SkToBool(fProxyRef.get()->instantiate(resourceProvider));
424 }
425
426 // 'peekTexture' should only ever be called after a successful 'instantiate' call
427 GrTexture* peekTexture() const {
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400428 SkASSERT(fProxyRef.get()->peekTexture());
429 return fProxyRef.get()->peekTexture();
Brian Salomone782f842018-07-31 13:53:11 -0400430 }
431
Brian Salomonee783962018-08-01 09:55:10 -0400432 GrTextureProxy* proxy() const { return fProxyRef.get(); }
Brian Salomone782f842018-07-31 13:53:11 -0400433 const GrSamplerState& samplerState() const { return fSamplerState; }
434
435 bool isInitialized() const { return SkToBool(fProxyRef.get()); }
436 /**
437 * For internal use by GrFragmentProcessor.
438 */
Brian Salomonee783962018-08-01 09:55:10 -0400439 const GrTextureProxyRef* proxyRef() const { return &fProxyRef; }
Brian Salomone782f842018-07-31 13:53:11 -0400440
441private:
Brian Salomonee783962018-08-01 09:55:10 -0400442 GrTextureProxyRef fProxyRef;
Brian Salomone782f842018-07-31 13:53:11 -0400443 GrSamplerState fSamplerState;
444};
445
446//////////////////////////////////////////////////////////////////////////////
447
448const GrFragmentProcessor::TextureSampler& GrFragmentProcessor::IthTextureSampler(int i) {
449 SK_ABORT("Illegal texture sampler index");
450 static const TextureSampler kBogus;
451 return kBogus;
452}
453
Brian Salomon587e08f2017-01-27 10:59:27 -0500454GR_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags)
455
bsalomon6251d172014-10-15 10:50:36 -0700456#endif