blob: 12733ca0626789bd58d60ef9f4e46a500cda0087 [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 */
Brian Salomone782f842018-07-31 13:53:11 -040041 template <typename T, int (GrFragmentProcessor::*COUNT)() const>
bsalomonb58a2b42016-09-26 06:55:02 -070042 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:
Brian Salomone782f842018-07-31 13:53:11 -040070 using TransformedCoordVars =
71 BuilderInputProvider<GrShaderVar, &GrFragmentProcessor::numCoordTransforms>;
72 using TextureSamplers =
73 BuilderInputProvider<SamplerHandle, &GrFragmentProcessor::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
Michael Ludwig231de032018-08-30 14:33:01 -040086 be nullptr in which case the fInputColor is set to "half4(1.0)"
87 (solid white) so this is guaranteed non-null.
88 TODO: Better system for communicating optimization info
bsalomon1a1aa932016-09-12 09:30:36 -070089 (e.g. input color is solid white, trans black, known to be opaque,
90 etc.) that allows the processor to communicate back similar known
91 info about its output.
92 @param transformedCoords Fragment shader variables containing the coords computed using
bsalomona624bf32016-09-20 09:12:47 -070093 each of the GrFragmentProcessor's GrCoordTransforms.
Brian Salomon0bbecb22016-11-17 11:38:22 -050094 @param texSamplers Contains one entry for each TextureSampler of the GrProcessor.
bsalomon1a1aa932016-09-12 09:30:36 -070095 These can be passed to the builder to emit texture reads in the
96 generated code.
bsalomon38ddbad2015-09-24 06:00:00 -070097 */
wangyix7c157a92015-07-22 15:08:53 -070098 struct EmitArgs {
cdalton85285412016-02-18 12:37:07 -080099 EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder,
egdaniel7ea439b2015-12-03 09:20:44 -0800100 GrGLSLUniformHandler* uniformHandler,
Brian Salomon94efbf52016-11-29 13:43:05 -0500101 const GrShaderCaps* caps,
wangyix7c157a92015-07-22 15:08:53 -0700102 const GrFragmentProcessor& fp,
103 const char* outputColor,
104 const char* inputColor,
bsalomona624bf32016-09-20 09:12:47 -0700105 const TransformedCoordVars& transformedCoordVars,
Brian Salomon662ea4b2018-07-12 14:53:49 -0400106 const TextureSamplers& textureSamplers)
Brian Salomone23bffd2017-06-02 11:01:10 -0400107 : fFragBuilder(fragBuilder)
108 , fUniformHandler(uniformHandler)
109 , fShaderCaps(caps)
110 , fFp(fp)
111 , fOutputColor(outputColor)
Michael Ludwig231de032018-08-30 14:33:01 -0400112 , fInputColor(inputColor ? inputColor : "half4(1.0)")
Brian Salomone23bffd2017-06-02 11:01:10 -0400113 , fTransformedCoords(transformedCoordVars)
Brian Salomon662ea4b2018-07-12 14:53:49 -0400114 , fTexSamplers(textureSamplers) {}
cdalton85285412016-02-18 12:37:07 -0800115 GrGLSLFPFragmentBuilder* fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -0800116 GrGLSLUniformHandler* fUniformHandler;
Brian Salomon1edc5b92016-11-29 13:43:46 -0500117 const GrShaderCaps* fShaderCaps;
wangyix7c157a92015-07-22 15:08:53 -0700118 const GrFragmentProcessor& fFp;
119 const char* fOutputColor;
120 const char* fInputColor;
bsalomona624bf32016-09-20 09:12:47 -0700121 const TransformedCoordVars& fTransformedCoords;
bsalomonb58a2b42016-09-26 06:55:02 -0700122 const TextureSamplers& fTexSamplers;
wangyix7c157a92015-07-22 15:08:53 -0700123 };
124
125 virtual void emitCode(EmitArgs&) = 0;
wangyix6af0c932015-07-22 10:21:17 -0700126
Michael Ludwigd3a357d2018-09-27 17:31:08 -0400127 // This does not recurse to any attached child processors. Recursing the entire processor tree
128 // is the responsibility of the caller.
egdaniel018fb622015-10-28 07:26:40 -0700129 void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor);
wangyix6af0c932015-07-22 10:21:17 -0700130
wangyixb1daa862015-08-18 11:29:31 -0700131 int numChildProcessors() const { return fChildProcessors.count(); }
132
bsalomonb58a2b42016-09-26 06:55:02 -0700133 GrGLSLFragmentProcessor* childProcessor(int index) {
wangyixb1daa862015-08-18 11:29:31 -0700134 return fChildProcessors[index];
135 }
136
Michael Ludwig231de032018-08-30 14:33:01 -0400137 // Emit the child with the default input color (solid white)
Ethan Nicholas2983f402017-05-08 09:36:08 -0400138 inline void emitChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs) {
Michael Ludwig231de032018-08-30 14:33:01 -0400139 this->emitChild(childIndex, nullptr, outputColor, parentArgs);
Ethan Nicholas2983f402017-05-08 09:36:08 -0400140 }
141
wangyix54a6b1a2015-09-08 08:41:51 -0700142 /** 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 -0700143 * emitChild will automatically extract the coords and samplers of that child and pass them
144 * on to the child's emitCode(). Also, any uniforms or functions emitted by the child will
145 * have their names mangled to prevent redefinitions. The output color name is also mangled
146 * therefore in an in/out param. It will be declared in mangled form by emitChild(). It is
147 * legal to pass nullptr as inputColor, since all fragment processors are required to work
148 * without an input color.
wangyix54a6b1a2015-09-08 08:41:51 -0700149 */
bsalomon38ddbad2015-09-24 06:00:00 -0700150 void emitChild(int childIndex, const char* inputColor, SkString* outputColor,
151 EmitArgs& parentArgs);
152
Michael Ludwig231de032018-08-30 14:33:01 -0400153 // Use the parent's output color to hold child's output, and use the
154 // default input color of solid white
Ethan Nicholas2983f402017-05-08 09:36:08 -0400155 inline void emitChild(int childIndex, EmitArgs& args) {
Michael Ludwig231de032018-08-30 14:33:01 -0400156 // null pointer cast required to disambiguate the function call
157 this->emitChild(childIndex, (const char*) nullptr, args);
Ethan Nicholas2983f402017-05-08 09:36:08 -0400158 }
159
bsalomon38ddbad2015-09-24 06:00:00 -0700160 /** 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); }
Brian Salomon4d3f5172018-06-07 14:42:52 -0400170 explicit Iter(std::unique_ptr<GrGLSLFragmentProcessor> fps[], int cnt) {
bsalomonb58a2b42016-09-26 06:55:02 -0700171 for (int i = cnt - 1; i >= 0; --i) {
Brian Salomon4d3f5172018-06-07 14:42:52 -0400172 fFPStack.push_back(fps[i].get());
bsalomonb58a2b42016-09-26 06:55:02 -0700173 }
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. */
Brian Salomonab015ef2017-04-04 10:15:51 -0400187 virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {}
wangyixb1daa862015-08-18 11:29:31 -0700188
wangyix6af0c932015-07-22 10:21:17 -0700189private:
bsalomon38ddbad2015-09-24 06:00:00 -0700190 void internalEmitChild(int, const char*, const char*, EmitArgs&);
191
egdaniel64c47282015-11-13 06:54:19 -0800192 SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors;
wangyixb1daa862015-08-18 11:29:31 -0700193
194 friend class GrFragmentProcessor;
wangyix6af0c932015-07-22 10:21:17 -0700195};
196
197#endif