blob: d2f00f8b336cd531ccdc2daed1aad3062d594e1a [file] [log] [blame]
wangyix6af0c932015-07-22 10:21:17 -07001/*
2 * Copyright 2013 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
egdaniel64c47282015-11-13 06:54:19 -08008#ifndef GrGLSLFragmentProcessor_DEFINED
9#define GrGLSLFragmentProcessor_DEFINED
wangyix6af0c932015-07-22 10:21:17 -070010
cdalton3f6f76f2016-04-11 12:18:09 -070011#include "GrFragmentProcessor.h"
bsalomon1a1aa932016-09-12 09:30:36 -070012#include "GrShaderVar.h"
egdaniel018fb622015-10-28 07:26:40 -070013#include "glsl/GrGLSLProgramDataManager.h"
cdalton3f6f76f2016-04-11 12:18:09 -070014#include "glsl/GrGLSLSampler.h"
wangyix6af0c932015-07-22 10:21:17 -070015
egdaniel7dc4bd02015-10-29 07:57:01 -070016class GrProcessor;
17class GrProcessorKeyBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -080018class GrGLSLCaps;
egdaniel8dcdedc2015-11-11 06:27:20 -080019class GrGLSLFPBuilder;
cdalton85285412016-02-18 12:37:07 -080020class GrGLSLFPFragmentBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -080021class GrGLSLUniformHandler;
wangyix6af0c932015-07-22 10:21:17 -070022
egdaniel64c47282015-11-13 06:54:19 -080023class GrGLSLFragmentProcessor {
wangyix6af0c932015-07-22 10:21:17 -070024public:
egdaniel64c47282015-11-13 06:54:19 -080025 GrGLSLFragmentProcessor() {}
wangyix6af0c932015-07-22 10:21:17 -070026
egdaniel64c47282015-11-13 06:54:19 -080027 virtual ~GrGLSLFragmentProcessor() {
wangyixb1daa862015-08-18 11:29:31 -070028 for (int i = 0; i < fChildProcessors.count(); ++i) {
halcanary385fe4d2015-08-26 13:07:48 -070029 delete fChildProcessors[i];
wangyixb1daa862015-08-18 11:29:31 -070030 }
31 }
wangyix6af0c932015-07-22 10:21:17 -070032
egdaniel018fb622015-10-28 07:26:40 -070033 typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
egdaniel09aa1fc2016-04-20 07:09:46 -070034 typedef GrGLSLProgramDataManager::UniformHandle SamplerHandle;
wangyix6af0c932015-07-22 10:21:17 -070035
bsalomonb58a2b42016-09-26 06:55:02 -070036private:
bsalomona624bf32016-09-20 09:12:47 -070037 /**
bsalomonb58a2b42016-09-26 06:55:02 -070038 * This class allows the shader builder to provide each GrGLSLFragmentProcesor with an array of
39 * generated variables where each generated variable corresponds to an element of an array on
40 * the GrFragmentProcessor that generated the GLSLFP. For example, this is used to provide a
41 * variable holding transformed coords for each GrCoordTransform owned by the FP.
bsalomona624bf32016-09-20 09:12:47 -070042 */
bsalomonb58a2b42016-09-26 06:55:02 -070043 template <typename T, typename FPBASE, int (FPBASE::*COUNT)() const>
44 class BuilderInputProvider {
bsalomona624bf32016-09-20 09:12:47 -070045 public:
bsalomonb58a2b42016-09-26 06:55:02 -070046 BuilderInputProvider(const GrFragmentProcessor* fp, const T* ts) : fFP(fp) , fTs(ts) {}
bsalomona624bf32016-09-20 09:12:47 -070047
bsalomonb58a2b42016-09-26 06:55:02 -070048 const T& operator[] (int i) const {
49 SkASSERT(i >= 0 && i < (fFP->*COUNT)());
50 return fTs[i];
bsalomona624bf32016-09-20 09:12:47 -070051 }
52
bsalomonb58a2b42016-09-26 06:55:02 -070053 BuilderInputProvider childInputs(int childIdx) const {
54 const GrFragmentProcessor* child = &fFP->childProcessor(childIdx);
55 GrFragmentProcessor::Iter iter(fFP);
56 int numToSkip = 0;
57 while (true) {
58 const GrFragmentProcessor* fp = iter.next();
59 if (fp == child) {
60 return BuilderInputProvider(child, fTs + numToSkip);
61 }
62 numToSkip += (fp->*COUNT)();
63 }
64 }
bsalomona624bf32016-09-20 09:12:47 -070065
66 private:
67 const GrFragmentProcessor* fFP;
bsalomonb58a2b42016-09-26 06:55:02 -070068 const T* fTs;
bsalomona624bf32016-09-20 09:12:47 -070069 };
70
bsalomonb58a2b42016-09-26 06:55:02 -070071public:
72 using TransformedCoordVars = BuilderInputProvider<GrShaderVar, GrFragmentProcessor,
73 &GrFragmentProcessor::numCoordTransforms>;
74 using TextureSamplers = BuilderInputProvider<SamplerHandle, GrProcessor,
75 &GrProcessor::numTextures>;
76 using BufferSamplers = BuilderInputProvider<SamplerHandle, GrProcessor,
77 &GrProcessor::numBuffers>;
78
wangyix6af0c932015-07-22 10:21:17 -070079 /** Called when the program stage should insert its code into the shaders. The code in each
80 shader will be in its own block ({}) and so locally scoped names will not collide across
81 stages.
82
bsalomon1a1aa932016-09-12 09:30:36 -070083 @param fragBuilder Interface used to emit code in the shaders.
84 @param fp The processor that generated this program stage.
85 @param key The key that was computed by GenKey() from the generating
86 GrProcessor.
87 @param outputColor A predefined vec4 in the FS in which the stage should place its
88 output color (or coverage).
89 @param inputColor A vec4 that holds the input color to the stage in the FS. This may
90 be nullptr in which case the implied input is solid white (all
91 ones). TODO: Better system for communicating optimization info
92 (e.g. input color is solid white, trans black, known to be opaque,
93 etc.) that allows the processor to communicate back similar known
94 info about its output.
95 @param transformedCoords Fragment shader variables containing the coords computed using
bsalomona624bf32016-09-20 09:12:47 -070096 each of the GrFragmentProcessor's GrCoordTransforms.
bsalomon1a1aa932016-09-12 09:30:36 -070097 @param texSamplers Contains one entry for each GrTextureAccess of the GrProcessor.
98 These can be passed to the builder to emit texture reads in the
99 generated code.
100 @param bufferSamplers Contains one entry for each GrBufferAccess of the GrProcessor.
101 These can be passed to the builder to emit buffer reads in the
102 generated code.
bsalomon38ddbad2015-09-24 06:00:00 -0700103 */
wangyix7c157a92015-07-22 15:08:53 -0700104 struct EmitArgs {
cdalton85285412016-02-18 12:37:07 -0800105 EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder,
egdaniel7ea439b2015-12-03 09:20:44 -0800106 GrGLSLUniformHandler* uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -0800107 const GrGLSLCaps* caps,
wangyix7c157a92015-07-22 15:08:53 -0700108 const GrFragmentProcessor& fp,
109 const char* outputColor,
110 const char* inputColor,
bsalomona624bf32016-09-20 09:12:47 -0700111 const TransformedCoordVars& transformedCoordVars,
bsalomonb58a2b42016-09-26 06:55:02 -0700112 const TextureSamplers& textureSamplers,
113 const BufferSamplers& bufferSamplers,
dvonbeck9b03e7b2016-08-01 11:01:56 -0700114 bool gpImplementsDistanceVector)
egdaniel7ea439b2015-12-03 09:20:44 -0800115 : fFragBuilder(fragBuilder)
116 , fUniformHandler(uniformHandler)
egdaniela2e3e0f2015-11-19 07:23:45 -0800117 , fGLSLCaps(caps)
wangyix7c157a92015-07-22 15:08:53 -0700118 , fFp(fp)
119 , fOutputColor(outputColor)
120 , fInputColor(inputColor)
bsalomona624bf32016-09-20 09:12:47 -0700121 , fTransformedCoords(transformedCoordVars)
bsalomonb58a2b42016-09-26 06:55:02 -0700122 , fTexSamplers(textureSamplers)
dvonbeck9b03e7b2016-08-01 11:01:56 -0700123 , fBufferSamplers(bufferSamplers)
bsalomon1a1aa932016-09-12 09:30:36 -0700124 , fGpImplementsDistanceVector(gpImplementsDistanceVector) {}
cdalton85285412016-02-18 12:37:07 -0800125 GrGLSLFPFragmentBuilder* fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -0800126 GrGLSLUniformHandler* fUniformHandler;
egdaniela2e3e0f2015-11-19 07:23:45 -0800127 const GrGLSLCaps* fGLSLCaps;
wangyix7c157a92015-07-22 15:08:53 -0700128 const GrFragmentProcessor& fFp;
129 const char* fOutputColor;
130 const char* fInputColor;
bsalomona624bf32016-09-20 09:12:47 -0700131 const TransformedCoordVars& fTransformedCoords;
bsalomonb58a2b42016-09-26 06:55:02 -0700132 const TextureSamplers& fTexSamplers;
133 const BufferSamplers& fBufferSamplers;
dvonbeck9b03e7b2016-08-01 11:01:56 -0700134 bool fGpImplementsDistanceVector;
wangyix7c157a92015-07-22 15:08:53 -0700135 };
136
137 virtual void emitCode(EmitArgs&) = 0;
wangyix6af0c932015-07-22 10:21:17 -0700138
egdaniel018fb622015-10-28 07:26:40 -0700139 void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor);
wangyix6af0c932015-07-22 10:21:17 -0700140
141 static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*) {}
142
wangyixb1daa862015-08-18 11:29:31 -0700143 int numChildProcessors() const { return fChildProcessors.count(); }
144
bsalomonb58a2b42016-09-26 06:55:02 -0700145 GrGLSLFragmentProcessor* childProcessor(int index) {
wangyixb1daa862015-08-18 11:29:31 -0700146 return fChildProcessors[index];
147 }
148
wangyix54a6b1a2015-09-08 08:41:51 -0700149 /** Will emit the code of a child proc in its own scope. Pass in the parent's EmitArgs and
bsalomon38ddbad2015-09-24 06:00:00 -0700150 * emitChild will automatically extract the coords and samplers of that child and pass them
151 * on to the child's emitCode(). Also, any uniforms or functions emitted by the child will
152 * have their names mangled to prevent redefinitions. The output color name is also mangled
153 * therefore in an in/out param. It will be declared in mangled form by emitChild(). It is
154 * legal to pass nullptr as inputColor, since all fragment processors are required to work
155 * without an input color.
wangyix54a6b1a2015-09-08 08:41:51 -0700156 */
bsalomon38ddbad2015-09-24 06:00:00 -0700157 void emitChild(int childIndex, const char* inputColor, SkString* outputColor,
158 EmitArgs& parentArgs);
159
160 /** Variation that uses the parent's output color variable to hold the child's output.*/
161 void emitChild(int childIndex, const char* inputColor, EmitArgs& parentArgs);
wangyix2a378432015-08-18 12:00:12 -0700162
bsalomonb58a2b42016-09-26 06:55:02 -0700163 /**
164 * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of
165 * GLSLFPS. This agrees with the traversal order of GrFragmentProcessor::Iter
166 */
167 class Iter : public SkNoncopyable {
168 public:
169 explicit Iter(GrGLSLFragmentProcessor* fp) { fFPStack.push_back(fp); }
170 explicit Iter(GrGLSLFragmentProcessor* fps[], int cnt) {
171 for (int i = cnt - 1; i >= 0; --i) {
172 fFPStack.push_back(fps[i]);
173 }
174 }
175 GrGLSLFragmentProcessor* next();
176
177 private:
178 SkSTArray<4, GrGLSLFragmentProcessor*, true> fFPStack;
179 };
180
wangyixb1daa862015-08-18 11:29:31 -0700181protected:
egdaniel64c47282015-11-13 06:54:19 -0800182 /** A GrGLSLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces
wangyixb1daa862015-08-18 11:29:31 -0700183 the same stage key; this function reads data from a GrFragmentProcessor and uploads any
184 uniform variables required by the shaders created in emitCode(). The GrFragmentProcessor
egdaniel64c47282015-11-13 06:54:19 -0800185 parameter is guaranteed to be of the same type that created this GrGLSLFragmentProcessor and
186 to have an identical processor key as the one that created this GrGLSLFragmentProcessor. */
wangyixb1daa862015-08-18 11:29:31 -0700187 // TODO update this to pass in GrFragmentProcessor
egdaniel018fb622015-10-28 07:26:40 -0700188 virtual void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) {}
wangyixb1daa862015-08-18 11:29:31 -0700189
wangyix6af0c932015-07-22 10:21:17 -0700190private:
bsalomon38ddbad2015-09-24 06:00:00 -0700191 void internalEmitChild(int, const char*, const char*, EmitArgs&);
192
egdaniel64c47282015-11-13 06:54:19 -0800193 SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors;
wangyixb1daa862015-08-18 11:29:31 -0700194
195 friend class GrFragmentProcessor;
wangyix6af0c932015-07-22 10:21:17 -0700196};
197
198#endif