blob: 8f903755eafef8c0011d51516ab06affbca6d3b6 [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"
Brian Salomonf9f45122016-11-29 11:59:17 -050014#include "glsl/GrGLSLUniformHandler.h"
wangyix6af0c932015-07-22 10:21:17 -070015
egdaniel7dc4bd02015-10-29 07:57:01 -070016class GrProcessor;
17class GrProcessorKeyBuilder;
egdaniel8dcdedc2015-11-11 06:27:20 -080018class GrGLSLFPBuilder;
cdalton85285412016-02-18 12:37:07 -080019class GrGLSLFPFragmentBuilder;
wangyix6af0c932015-07-22 10:21:17 -070020
egdaniel64c47282015-11-13 06:54:19 -080021class GrGLSLFragmentProcessor {
wangyix6af0c932015-07-22 10:21:17 -070022public:
egdaniel64c47282015-11-13 06:54:19 -080023 GrGLSLFragmentProcessor() {}
wangyix6af0c932015-07-22 10:21:17 -070024
egdaniel64c47282015-11-13 06:54:19 -080025 virtual ~GrGLSLFragmentProcessor() {
wangyixb1daa862015-08-18 11:29:31 -070026 for (int i = 0; i < fChildProcessors.count(); ++i) {
halcanary385fe4d2015-08-26 13:07:48 -070027 delete fChildProcessors[i];
wangyixb1daa862015-08-18 11:29:31 -070028 }
29 }
wangyix6af0c932015-07-22 10:21:17 -070030
Brian Salomonf9f45122016-11-29 11:59:17 -050031 using UniformHandle = GrGLSLUniformHandler::UniformHandle;
32 using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
wangyix6af0c932015-07-22 10:21:17 -070033
bsalomonb58a2b42016-09-26 06:55:02 -070034private:
bsalomona624bf32016-09-20 09:12:47 -070035 /**
bsalomonb58a2b42016-09-26 06:55:02 -070036 * This class allows the shader builder to provide each GrGLSLFragmentProcesor with an array of
37 * generated variables where each generated variable corresponds to an element of an array on
38 * the GrFragmentProcessor that generated the GLSLFP. For example, this is used to provide a
39 * variable holding transformed coords for each GrCoordTransform owned by the FP.
bsalomona624bf32016-09-20 09:12:47 -070040 */
bsalomonb58a2b42016-09-26 06:55:02 -070041 template <typename T, typename FPBASE, int (FPBASE::*COUNT)() const>
42 class BuilderInputProvider {
bsalomona624bf32016-09-20 09:12:47 -070043 public:
bsalomonb58a2b42016-09-26 06:55:02 -070044 BuilderInputProvider(const GrFragmentProcessor* fp, const T* ts) : fFP(fp) , fTs(ts) {}
bsalomona624bf32016-09-20 09:12:47 -070045
bsalomonb58a2b42016-09-26 06:55:02 -070046 const T& operator[] (int i) const {
47 SkASSERT(i >= 0 && i < (fFP->*COUNT)());
48 return fTs[i];
bsalomona624bf32016-09-20 09:12:47 -070049 }
50
bsalomonb58a2b42016-09-26 06:55:02 -070051 BuilderInputProvider childInputs(int childIdx) const {
52 const GrFragmentProcessor* child = &fFP->childProcessor(childIdx);
53 GrFragmentProcessor::Iter iter(fFP);
54 int numToSkip = 0;
55 while (true) {
56 const GrFragmentProcessor* fp = iter.next();
57 if (fp == child) {
58 return BuilderInputProvider(child, fTs + numToSkip);
59 }
60 numToSkip += (fp->*COUNT)();
61 }
62 }
bsalomona624bf32016-09-20 09:12:47 -070063
64 private:
65 const GrFragmentProcessor* fFP;
bsalomonb58a2b42016-09-26 06:55:02 -070066 const T* fTs;
bsalomona624bf32016-09-20 09:12:47 -070067 };
68
bsalomonb58a2b42016-09-26 06:55:02 -070069public:
70 using TransformedCoordVars = BuilderInputProvider<GrShaderVar, GrFragmentProcessor,
71 &GrFragmentProcessor::numCoordTransforms>;
Brian Salomonab015ef2017-04-04 10:15:51 -040072 using TextureSamplers = BuilderInputProvider<SamplerHandle, GrResourceIOProcessor,
73 &GrResourceIOProcessor::numTextureSamplers>;
bsalomonb58a2b42016-09-26 06:55:02 -070074
wangyix6af0c932015-07-22 10:21:17 -070075 /** Called when the program stage should insert its code into the shaders. The code in each
76 shader will be in its own block ({}) and so locally scoped names will not collide across
77 stages.
78
bsalomon1a1aa932016-09-12 09:30:36 -070079 @param fragBuilder Interface used to emit code in the shaders.
80 @param fp The processor that generated this program stage.
81 @param key The key that was computed by GenKey() from the generating
82 GrProcessor.
Ethan Nicholasf7b88202017-09-18 14:10:39 -040083 @param outputColor A predefined half4 in the FS in which the stage should place its
bsalomon1a1aa932016-09-12 09:30:36 -070084 output color (or coverage).
Ethan Nicholasf7b88202017-09-18 14:10:39 -040085 @param inputColor A half4 that holds the input color to the stage in the FS. This may
bsalomon1a1aa932016-09-12 09:30:36 -070086 be nullptr in which case the implied input is solid white (all
87 ones). TODO: Better system for communicating optimization info
88 (e.g. input color is solid white, trans black, known to be opaque,
89 etc.) that allows the processor to communicate back similar known
90 info about its output.
91 @param transformedCoords Fragment shader variables containing the coords computed using
bsalomona624bf32016-09-20 09:12:47 -070092 each of the GrFragmentProcessor's GrCoordTransforms.
Brian Salomon0bbecb22016-11-17 11:38:22 -050093 @param texSamplers Contains one entry for each TextureSampler of the GrProcessor.
bsalomon1a1aa932016-09-12 09:30:36 -070094 These can be passed to the builder to emit texture reads in the
95 generated code.
bsalomon38ddbad2015-09-24 06:00:00 -070096 */
wangyix7c157a92015-07-22 15:08:53 -070097 struct EmitArgs {
cdalton85285412016-02-18 12:37:07 -080098 EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder,
egdaniel7ea439b2015-12-03 09:20:44 -080099 GrGLSLUniformHandler* uniformHandler,
Brian Salomon94efbf52016-11-29 13:43:05 -0500100 const GrShaderCaps* caps,
wangyix7c157a92015-07-22 15:08:53 -0700101 const GrFragmentProcessor& fp,
102 const char* outputColor,
103 const char* inputColor,
bsalomona624bf32016-09-20 09:12:47 -0700104 const TransformedCoordVars& transformedCoordVars,
Brian Salomon662ea4b2018-07-12 14:53:49 -0400105 const TextureSamplers& textureSamplers)
Brian Salomone23bffd2017-06-02 11:01:10 -0400106 : fFragBuilder(fragBuilder)
107 , fUniformHandler(uniformHandler)
108 , fShaderCaps(caps)
109 , fFp(fp)
110 , fOutputColor(outputColor)
111 , fInputColor(inputColor)
112 , fTransformedCoords(transformedCoordVars)
Brian Salomon662ea4b2018-07-12 14:53:49 -0400113 , fTexSamplers(textureSamplers) {}
cdalton85285412016-02-18 12:37:07 -0800114 GrGLSLFPFragmentBuilder* fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -0800115 GrGLSLUniformHandler* fUniformHandler;
Brian Salomon1edc5b92016-11-29 13:43:46 -0500116 const GrShaderCaps* fShaderCaps;
wangyix7c157a92015-07-22 15:08:53 -0700117 const GrFragmentProcessor& fFp;
118 const char* fOutputColor;
119 const char* fInputColor;
bsalomona624bf32016-09-20 09:12:47 -0700120 const TransformedCoordVars& fTransformedCoords;
bsalomonb58a2b42016-09-26 06:55:02 -0700121 const TextureSamplers& fTexSamplers;
wangyix7c157a92015-07-22 15:08:53 -0700122 };
123
124 virtual void emitCode(EmitArgs&) = 0;
wangyix6af0c932015-07-22 10:21:17 -0700125
egdaniel018fb622015-10-28 07:26:40 -0700126 void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor);
wangyix6af0c932015-07-22 10:21:17 -0700127
wangyixb1daa862015-08-18 11:29:31 -0700128 int numChildProcessors() const { return fChildProcessors.count(); }
129
bsalomonb58a2b42016-09-26 06:55:02 -0700130 GrGLSLFragmentProcessor* childProcessor(int index) {
wangyixb1daa862015-08-18 11:29:31 -0700131 return fChildProcessors[index];
132 }
133
Ethan Nicholas2983f402017-05-08 09:36:08 -0400134 inline void emitChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs) {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400135 this->emitChild(childIndex, "half4(1.0)", outputColor, parentArgs);
Ethan Nicholas2983f402017-05-08 09:36:08 -0400136 }
137
wangyix54a6b1a2015-09-08 08:41:51 -0700138 /** 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 -0700139 * emitChild will automatically extract the coords and samplers of that child and pass them
140 * on to the child's emitCode(). Also, any uniforms or functions emitted by the child will
141 * have their names mangled to prevent redefinitions. The output color name is also mangled
142 * therefore in an in/out param. It will be declared in mangled form by emitChild(). It is
143 * legal to pass nullptr as inputColor, since all fragment processors are required to work
144 * without an input color.
wangyix54a6b1a2015-09-08 08:41:51 -0700145 */
bsalomon38ddbad2015-09-24 06:00:00 -0700146 void emitChild(int childIndex, const char* inputColor, SkString* outputColor,
147 EmitArgs& parentArgs);
148
Ethan Nicholas2983f402017-05-08 09:36:08 -0400149 inline void emitChild(int childIndex, EmitArgs& args) {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400150 this->emitChild(childIndex, "half4(1.0)", args);
Ethan Nicholas2983f402017-05-08 09:36:08 -0400151 }
152
bsalomon38ddbad2015-09-24 06:00:00 -0700153 /** Variation that uses the parent's output color variable to hold the child's output.*/
154 void emitChild(int childIndex, const char* inputColor, EmitArgs& parentArgs);
wangyix2a378432015-08-18 12:00:12 -0700155
bsalomonb58a2b42016-09-26 06:55:02 -0700156 /**
157 * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of
158 * GLSLFPS. This agrees with the traversal order of GrFragmentProcessor::Iter
159 */
160 class Iter : public SkNoncopyable {
161 public:
162 explicit Iter(GrGLSLFragmentProcessor* fp) { fFPStack.push_back(fp); }
Brian Salomon4d3f5172018-06-07 14:42:52 -0400163 explicit Iter(std::unique_ptr<GrGLSLFragmentProcessor> fps[], int cnt) {
bsalomonb58a2b42016-09-26 06:55:02 -0700164 for (int i = cnt - 1; i >= 0; --i) {
Brian Salomon4d3f5172018-06-07 14:42:52 -0400165 fFPStack.push_back(fps[i].get());
bsalomonb58a2b42016-09-26 06:55:02 -0700166 }
167 }
168 GrGLSLFragmentProcessor* next();
169
170 private:
171 SkSTArray<4, GrGLSLFragmentProcessor*, true> fFPStack;
172 };
173
wangyixb1daa862015-08-18 11:29:31 -0700174protected:
egdaniel64c47282015-11-13 06:54:19 -0800175 /** A GrGLSLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces
wangyixb1daa862015-08-18 11:29:31 -0700176 the same stage key; this function reads data from a GrFragmentProcessor and uploads any
177 uniform variables required by the shaders created in emitCode(). The GrFragmentProcessor
egdaniel64c47282015-11-13 06:54:19 -0800178 parameter is guaranteed to be of the same type that created this GrGLSLFragmentProcessor and
179 to have an identical processor key as the one that created this GrGLSLFragmentProcessor. */
Brian Salomonab015ef2017-04-04 10:15:51 -0400180 virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {}
wangyixb1daa862015-08-18 11:29:31 -0700181
wangyix6af0c932015-07-22 10:21:17 -0700182private:
bsalomon38ddbad2015-09-24 06:00:00 -0700183 void internalEmitChild(int, const char*, const char*, EmitArgs&);
184
egdaniel64c47282015-11-13 06:54:19 -0800185 SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors;
wangyixb1daa862015-08-18 11:29:31 -0700186
187 friend class GrFragmentProcessor;
wangyix6af0c932015-07-22 10:21:17 -0700188};
189
190#endif