blob: c9971a2115c3e200ffbc31ef11ec2b91d68f1a10 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/gpu/GrFragmentProcessor.h"
12#include "src/gpu/GrShaderVar.h"
13#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
14#include "src/gpu/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
Robert Phillips94ade752018-10-09 12:32:31 -040051 int count() const { return (fFP->*COUNT)(); }
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:
Brian Salomone782f842018-07-31 13:53:11 -040072 using TransformedCoordVars =
73 BuilderInputProvider<GrShaderVar, &GrFragmentProcessor::numCoordTransforms>;
74 using TextureSamplers =
75 BuilderInputProvider<SamplerHandle, &GrFragmentProcessor::numTextureSamplers>;
bsalomonb58a2b42016-09-26 06:55:02 -070076
wangyix6af0c932015-07-22 10:21:17 -070077 /** Called when the program stage should insert its code into the shaders. The code in each
78 shader will be in its own block ({}) and so locally scoped names will not collide across
79 stages.
80
bsalomon1a1aa932016-09-12 09:30:36 -070081 @param fragBuilder Interface used to emit code in the shaders.
82 @param fp The processor that generated this program stage.
83 @param key The key that was computed by GenKey() from the generating
84 GrProcessor.
Ethan Nicholasf7b88202017-09-18 14:10:39 -040085 @param outputColor A predefined half4 in the FS in which the stage should place its
bsalomon1a1aa932016-09-12 09:30:36 -070086 output color (or coverage).
Ethan Nicholasf7b88202017-09-18 14:10:39 -040087 @param inputColor A half4 that holds the input color to the stage in the FS. This may
Michael Ludwig231de032018-08-30 14:33:01 -040088 be nullptr in which case the fInputColor is set to "half4(1.0)"
89 (solid white) so this is guaranteed non-null.
90 TODO: Better system for communicating optimization info
bsalomon1a1aa932016-09-12 09:30:36 -070091 (e.g. input color is solid white, trans black, known to be opaque,
92 etc.) that allows the processor to communicate back similar known
93 info about its output.
94 @param transformedCoords Fragment shader variables containing the coords computed using
bsalomona624bf32016-09-20 09:12:47 -070095 each of the GrFragmentProcessor's GrCoordTransforms.
Brian Salomon0bbecb22016-11-17 11:38:22 -050096 @param texSamplers Contains one entry for each TextureSampler of the GrProcessor.
bsalomon1a1aa932016-09-12 09:30:36 -070097 These can be passed to the builder to emit texture reads in the
98 generated code.
bsalomon38ddbad2015-09-24 06:00:00 -070099 */
wangyix7c157a92015-07-22 15:08:53 -0700100 struct EmitArgs {
cdalton85285412016-02-18 12:37:07 -0800101 EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder,
egdaniel7ea439b2015-12-03 09:20:44 -0800102 GrGLSLUniformHandler* uniformHandler,
Brian Salomon94efbf52016-11-29 13:43:05 -0500103 const GrShaderCaps* caps,
wangyix7c157a92015-07-22 15:08:53 -0700104 const GrFragmentProcessor& fp,
105 const char* outputColor,
106 const char* inputColor,
bsalomona624bf32016-09-20 09:12:47 -0700107 const TransformedCoordVars& transformedCoordVars,
Brian Salomon662ea4b2018-07-12 14:53:49 -0400108 const TextureSamplers& textureSamplers)
Brian Salomone23bffd2017-06-02 11:01:10 -0400109 : fFragBuilder(fragBuilder)
110 , fUniformHandler(uniformHandler)
111 , fShaderCaps(caps)
112 , fFp(fp)
113 , fOutputColor(outputColor)
Michael Ludwig231de032018-08-30 14:33:01 -0400114 , fInputColor(inputColor ? inputColor : "half4(1.0)")
Brian Salomone23bffd2017-06-02 11:01:10 -0400115 , fTransformedCoords(transformedCoordVars)
Brian Salomon662ea4b2018-07-12 14:53:49 -0400116 , fTexSamplers(textureSamplers) {}
cdalton85285412016-02-18 12:37:07 -0800117 GrGLSLFPFragmentBuilder* fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -0800118 GrGLSLUniformHandler* fUniformHandler;
Brian Salomon1edc5b92016-11-29 13:43:46 -0500119 const GrShaderCaps* fShaderCaps;
wangyix7c157a92015-07-22 15:08:53 -0700120 const GrFragmentProcessor& fFp;
121 const char* fOutputColor;
122 const char* fInputColor;
bsalomona624bf32016-09-20 09:12:47 -0700123 const TransformedCoordVars& fTransformedCoords;
bsalomonb58a2b42016-09-26 06:55:02 -0700124 const TextureSamplers& fTexSamplers;
wangyix7c157a92015-07-22 15:08:53 -0700125 };
126
127 virtual void emitCode(EmitArgs&) = 0;
wangyix6af0c932015-07-22 10:21:17 -0700128
Michael Ludwigd3a357d2018-09-27 17:31:08 -0400129 // This does not recurse to any attached child processors. Recursing the entire processor tree
130 // is the responsibility of the caller.
egdaniel018fb622015-10-28 07:26:40 -0700131 void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor);
wangyix6af0c932015-07-22 10:21:17 -0700132
wangyixb1daa862015-08-18 11:29:31 -0700133 int numChildProcessors() const { return fChildProcessors.count(); }
134
bsalomonb58a2b42016-09-26 06:55:02 -0700135 GrGLSLFragmentProcessor* childProcessor(int index) {
wangyixb1daa862015-08-18 11:29:31 -0700136 return fChildProcessors[index];
137 }
138
Ethan Nicholasc6dce5a2019-07-24 16:51:36 -0400139 // Invoke the child with the default input color (solid white)
140 inline void invokeChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs) {
141 this->invokeChild(childIndex, nullptr, outputColor, parentArgs);
Ethan Nicholas2983f402017-05-08 09:36:08 -0400142 }
143
Ethan Nicholasc6dce5a2019-07-24 16:51:36 -0400144 /** Invokes a child proc in its own scope. Pass in the parent's EmitArgs and invokeChild will
145 * automatically extract the coords and samplers of that child and pass them on to the child's
146 * emitCode(). Also, any uniforms or functions emitted by the child will have their names
147 * mangled to prevent redefinitions. The output color name is also mangled therefore in an
148 * in/out param. It will be declared in mangled form by invokeChild(). It is legal to pass
149 * nullptr as inputColor, since all fragment processors are required to work without an input
150 * color.
wangyix54a6b1a2015-09-08 08:41:51 -0700151 */
Ethan Nicholasc6dce5a2019-07-24 16:51:36 -0400152 void invokeChild(int childIndex, const char* inputColor, SkString* outputColor,
153 EmitArgs& parentArgs);
bsalomon38ddbad2015-09-24 06:00:00 -0700154
Michael Ludwig231de032018-08-30 14:33:01 -0400155 // Use the parent's output color to hold child's output, and use the
156 // default input color of solid white
Ethan Nicholasc6dce5a2019-07-24 16:51:36 -0400157 inline void invokeChild(int childIndex, EmitArgs& args) {
Michael Ludwig231de032018-08-30 14:33:01 -0400158 // null pointer cast required to disambiguate the function call
Ethan Nicholasc6dce5a2019-07-24 16:51:36 -0400159 this->invokeChild(childIndex, (const char*) nullptr, args);
Ethan Nicholas2983f402017-05-08 09:36:08 -0400160 }
161
Ethan Nicholas6ad52892019-05-03 13:13:42 +0000162 /** Variation that uses the parent's output color variable to hold the child's output.*/
Ethan Nicholasc6dce5a2019-07-24 16:51:36 -0400163 void invokeChild(int childIndex, const char* inputColor, EmitArgs& parentArgs);
Ethan Nicholas6ad52892019-05-03 13:13:42 +0000164
bsalomonb58a2b42016-09-26 06:55:02 -0700165 /**
166 * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of
167 * GLSLFPS. This agrees with the traversal order of GrFragmentProcessor::Iter
168 */
169 class Iter : public SkNoncopyable {
170 public:
171 explicit Iter(GrGLSLFragmentProcessor* fp) { fFPStack.push_back(fp); }
Brian Salomon4d3f5172018-06-07 14:42:52 -0400172 explicit Iter(std::unique_ptr<GrGLSLFragmentProcessor> fps[], int cnt) {
bsalomonb58a2b42016-09-26 06:55:02 -0700173 for (int i = cnt - 1; i >= 0; --i) {
Brian Salomon4d3f5172018-06-07 14:42:52 -0400174 fFPStack.push_back(fps[i].get());
bsalomonb58a2b42016-09-26 06:55:02 -0700175 }
176 }
177 GrGLSLFragmentProcessor* next();
178
179 private:
180 SkSTArray<4, GrGLSLFragmentProcessor*, true> fFPStack;
181 };
182
wangyixb1daa862015-08-18 11:29:31 -0700183protected:
egdaniel64c47282015-11-13 06:54:19 -0800184 /** A GrGLSLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces
wangyixb1daa862015-08-18 11:29:31 -0700185 the same stage key; this function reads data from a GrFragmentProcessor and uploads any
186 uniform variables required by the shaders created in emitCode(). The GrFragmentProcessor
egdaniel64c47282015-11-13 06:54:19 -0800187 parameter is guaranteed to be of the same type that created this GrGLSLFragmentProcessor and
188 to have an identical processor key as the one that created this GrGLSLFragmentProcessor. */
Brian Salomonab015ef2017-04-04 10:15:51 -0400189 virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {}
wangyixb1daa862015-08-18 11:29:31 -0700190
wangyix6af0c932015-07-22 10:21:17 -0700191private:
Ethan Nicholasc6dce5a2019-07-24 16:51:36 -0400192 void internalInvokeChild(int, const char*, const char*, EmitArgs&);
193
194 // one per child; either not present or empty string if not yet emitted
195 SkTArray<SkString> fFunctionNames;
bsalomon38ddbad2015-09-24 06:00:00 -0700196
egdaniel64c47282015-11-13 06:54:19 -0800197 SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors;
wangyixb1daa862015-08-18 11:29:31 -0700198
199 friend class GrFragmentProcessor;
wangyix6af0c932015-07-22 10:21:17 -0700200};
201
202#endif