blob: ad441d8efc302fda3575da8fe22ee5ee4790e572 [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"
Ethan Nicholasd4efe682019-08-29 16:10:13 -040013#include "src/gpu/glsl/GrGLSLPrimitiveProcessor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
15#include "src/gpu/glsl/GrGLSLUniformHandler.h"
Ethan Nicholasd4efe682019-08-29 16:10:13 -040016#include "src/sksl/SkSLString.h"
wangyix6af0c932015-07-22 10:21:17 -070017
egdaniel7dc4bd02015-10-29 07:57:01 -070018class GrProcessor;
19class GrProcessorKeyBuilder;
egdaniel8dcdedc2015-11-11 06:27:20 -080020class GrGLSLFPBuilder;
cdalton85285412016-02-18 12:37:07 -080021class GrGLSLFPFragmentBuilder;
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
Brian Salomonf9f45122016-11-29 11:59:17 -050033 using UniformHandle = GrGLSLUniformHandler::UniformHandle;
34 using SamplerHandle = GrGLSLUniformHandler::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 */
Brian Salomone782f842018-07-31 13:53:11 -040043 template <typename T, int (GrFragmentProcessor::*COUNT)() const>
bsalomonb58a2b42016-09-26 06:55:02 -070044 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
Robert Phillips94ade752018-10-09 12:32:31 -040053 int count() const { return (fFP->*COUNT)(); }
54
bsalomonb58a2b42016-09-26 06:55:02 -070055 BuilderInputProvider childInputs(int childIdx) const {
56 const GrFragmentProcessor* child = &fFP->childProcessor(childIdx);
57 GrFragmentProcessor::Iter iter(fFP);
58 int numToSkip = 0;
59 while (true) {
60 const GrFragmentProcessor* fp = iter.next();
61 if (fp == child) {
62 return BuilderInputProvider(child, fTs + numToSkip);
63 }
64 numToSkip += (fp->*COUNT)();
65 }
66 }
bsalomona624bf32016-09-20 09:12:47 -070067
68 private:
69 const GrFragmentProcessor* fFP;
bsalomonb58a2b42016-09-26 06:55:02 -070070 const T* fTs;
bsalomona624bf32016-09-20 09:12:47 -070071 };
72
bsalomonb58a2b42016-09-26 06:55:02 -070073public:
Ethan Nicholasd4efe682019-08-29 16:10:13 -040074 using TransformedCoordVars = BuilderInputProvider<GrGLSLPrimitiveProcessor::TransformVar,
75 &GrFragmentProcessor::numCoordTransforms>;
Brian Salomone782f842018-07-31 13:53:11 -040076 using TextureSamplers =
77 BuilderInputProvider<SamplerHandle, &GrFragmentProcessor::numTextureSamplers>;
bsalomonb58a2b42016-09-26 06:55:02 -070078
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.
Ethan Nicholasf7b88202017-09-18 14:10:39 -040087 @param outputColor A predefined half4 in the FS in which the stage should place its
bsalomon1a1aa932016-09-12 09:30:36 -070088 output color (or coverage).
Ethan Nicholasf7b88202017-09-18 14:10:39 -040089 @param inputColor A half4 that holds the input color to the stage in the FS. This may
Michael Ludwig231de032018-08-30 14:33:01 -040090 be nullptr in which case the fInputColor is set to "half4(1.0)"
91 (solid white) so this is guaranteed non-null.
92 TODO: Better system for communicating optimization info
bsalomon1a1aa932016-09-12 09:30:36 -070093 (e.g. input color is solid white, trans black, known to be opaque,
94 etc.) that allows the processor to communicate back similar known
95 info about its output.
96 @param transformedCoords Fragment shader variables containing the coords computed using
bsalomona624bf32016-09-20 09:12:47 -070097 each of the GrFragmentProcessor's GrCoordTransforms.
Brian Salomon0bbecb22016-11-17 11:38:22 -050098 @param texSamplers Contains one entry for each TextureSampler of the GrProcessor.
bsalomon1a1aa932016-09-12 09:30:36 -070099 These can be passed to the builder to emit texture reads in the
100 generated code.
bsalomon38ddbad2015-09-24 06:00:00 -0700101 */
wangyix7c157a92015-07-22 15:08:53 -0700102 struct EmitArgs {
cdalton85285412016-02-18 12:37:07 -0800103 EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder,
egdaniel7ea439b2015-12-03 09:20:44 -0800104 GrGLSLUniformHandler* uniformHandler,
Brian Salomon94efbf52016-11-29 13:43:05 -0500105 const GrShaderCaps* caps,
wangyix7c157a92015-07-22 15:08:53 -0700106 const GrFragmentProcessor& fp,
107 const char* outputColor,
108 const char* inputColor,
bsalomona624bf32016-09-20 09:12:47 -0700109 const TransformedCoordVars& transformedCoordVars,
Brian Salomon662ea4b2018-07-12 14:53:49 -0400110 const TextureSamplers& textureSamplers)
Brian Salomone23bffd2017-06-02 11:01:10 -0400111 : fFragBuilder(fragBuilder)
112 , fUniformHandler(uniformHandler)
113 , fShaderCaps(caps)
114 , fFp(fp)
115 , fOutputColor(outputColor)
Michael Ludwig231de032018-08-30 14:33:01 -0400116 , fInputColor(inputColor ? inputColor : "half4(1.0)")
Brian Salomone23bffd2017-06-02 11:01:10 -0400117 , fTransformedCoords(transformedCoordVars)
Brian Salomon662ea4b2018-07-12 14:53:49 -0400118 , fTexSamplers(textureSamplers) {}
cdalton85285412016-02-18 12:37:07 -0800119 GrGLSLFPFragmentBuilder* fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -0800120 GrGLSLUniformHandler* fUniformHandler;
Brian Salomon1edc5b92016-11-29 13:43:46 -0500121 const GrShaderCaps* fShaderCaps;
wangyix7c157a92015-07-22 15:08:53 -0700122 const GrFragmentProcessor& fFp;
123 const char* fOutputColor;
124 const char* fInputColor;
bsalomona624bf32016-09-20 09:12:47 -0700125 const TransformedCoordVars& fTransformedCoords;
bsalomonb58a2b42016-09-26 06:55:02 -0700126 const TextureSamplers& fTexSamplers;
wangyix7c157a92015-07-22 15:08:53 -0700127 };
128
129 virtual void emitCode(EmitArgs&) = 0;
wangyix6af0c932015-07-22 10:21:17 -0700130
Michael Ludwigd3a357d2018-09-27 17:31:08 -0400131 // This does not recurse to any attached child processors. Recursing the entire processor tree
132 // is the responsibility of the caller.
egdaniel018fb622015-10-28 07:26:40 -0700133 void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor);
wangyix6af0c932015-07-22 10:21:17 -0700134
wangyixb1daa862015-08-18 11:29:31 -0700135 int numChildProcessors() const { return fChildProcessors.count(); }
136
bsalomonb58a2b42016-09-26 06:55:02 -0700137 GrGLSLFragmentProcessor* childProcessor(int index) {
wangyixb1daa862015-08-18 11:29:31 -0700138 return fChildProcessors[index];
139 }
140
Ethan Nicholasc6dce5a2019-07-24 16:51:36 -0400141 // Invoke the child with the default input color (solid white)
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400142 inline void invokeChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs,
143 SkSL::String skslCoords = "") {
144 this->invokeChild(childIndex, nullptr, outputColor, parentArgs, skslCoords);
Ethan Nicholas2983f402017-05-08 09:36:08 -0400145 }
146
Ethan Nicholasc6dce5a2019-07-24 16:51:36 -0400147 /** Invokes a child proc in its own scope. Pass in the parent's EmitArgs and invokeChild will
148 * automatically extract the coords and samplers of that child and pass them on to the child's
149 * emitCode(). Also, any uniforms or functions emitted by the child will have their names
150 * mangled to prevent redefinitions. The output color name is also mangled therefore in an
151 * in/out param. It will be declared in mangled form by invokeChild(). It is legal to pass
152 * nullptr as inputColor, since all fragment processors are required to work without an input
153 * color.
wangyix54a6b1a2015-09-08 08:41:51 -0700154 */
Ethan Nicholasc6dce5a2019-07-24 16:51:36 -0400155 void invokeChild(int childIndex, const char* inputColor, SkString* outputColor,
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400156 EmitArgs& parentArgs, SkSL::String skslCoords = "");
bsalomon38ddbad2015-09-24 06:00:00 -0700157
Michael Ludwig231de032018-08-30 14:33:01 -0400158 // Use the parent's output color to hold child's output, and use the
159 // default input color of solid white
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400160 inline void invokeChild(int childIndex, EmitArgs& args, SkSL::String skslCoords = "") {
Michael Ludwig231de032018-08-30 14:33:01 -0400161 // null pointer cast required to disambiguate the function call
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400162 this->invokeChild(childIndex, (const char*) nullptr, args, skslCoords);
Ethan Nicholas2983f402017-05-08 09:36:08 -0400163 }
164
Ethan Nicholas6ad52892019-05-03 13:13:42 +0000165 /** Variation that uses the parent's output color variable to hold the child's output.*/
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400166 void invokeChild(int childIndex, const char* inputColor, EmitArgs& parentArgs,
167 SkSL::String skslCoords = "");
Ethan Nicholas6ad52892019-05-03 13:13:42 +0000168
bsalomonb58a2b42016-09-26 06:55:02 -0700169 /**
170 * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of
171 * GLSLFPS. This agrees with the traversal order of GrFragmentProcessor::Iter
172 */
173 class Iter : public SkNoncopyable {
174 public:
175 explicit Iter(GrGLSLFragmentProcessor* fp) { fFPStack.push_back(fp); }
Brian Salomon4d3f5172018-06-07 14:42:52 -0400176 explicit Iter(std::unique_ptr<GrGLSLFragmentProcessor> fps[], int cnt) {
bsalomonb58a2b42016-09-26 06:55:02 -0700177 for (int i = cnt - 1; i >= 0; --i) {
Brian Salomon4d3f5172018-06-07 14:42:52 -0400178 fFPStack.push_back(fps[i].get());
bsalomonb58a2b42016-09-26 06:55:02 -0700179 }
180 }
181 GrGLSLFragmentProcessor* next();
182
183 private:
184 SkSTArray<4, GrGLSLFragmentProcessor*, true> fFPStack;
185 };
186
wangyixb1daa862015-08-18 11:29:31 -0700187protected:
egdaniel64c47282015-11-13 06:54:19 -0800188 /** A GrGLSLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces
wangyixb1daa862015-08-18 11:29:31 -0700189 the same stage key; this function reads data from a GrFragmentProcessor and uploads any
190 uniform variables required by the shaders created in emitCode(). The GrFragmentProcessor
egdaniel64c47282015-11-13 06:54:19 -0800191 parameter is guaranteed to be of the same type that created this GrGLSLFragmentProcessor and
192 to have an identical processor key as the one that created this GrGLSLFragmentProcessor. */
Brian Salomonab015ef2017-04-04 10:15:51 -0400193 virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {}
wangyixb1daa862015-08-18 11:29:31 -0700194
wangyix6af0c932015-07-22 10:21:17 -0700195private:
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400196 void writeChildCall(GrGLSLFPFragmentBuilder* fragBuilder, int childIndex,
197 TransformedCoordVars coordVars, const char* inputColor,
198 const char* outputColor, EmitArgs& args,
199 SkSL::String skslCoords);
200
201 void internalInvokeChild(int, const char*, const char*, EmitArgs&, SkSL::String);
Ethan Nicholasc6dce5a2019-07-24 16:51:36 -0400202
203 // one per child; either not present or empty string if not yet emitted
204 SkTArray<SkString> fFunctionNames;
bsalomon38ddbad2015-09-24 06:00:00 -0700205
egdaniel64c47282015-11-13 06:54:19 -0800206 SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors;
wangyixb1daa862015-08-18 11:29:31 -0700207
208 friend class GrFragmentProcessor;
wangyix6af0c932015-07-22 10:21:17 -0700209};
210
211#endif