1/*
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
8#ifndef GrGLSLFragmentProcessor_DEFINED
9#define GrGLSLFragmentProcessor_DEFINED
10
11#include "src/gpu/GrFragmentProcessor.h"
12#include "src/gpu/GrShaderVar.h"
13#include "src/gpu/glsl/GrGLSLPrimitiveProcessor.h"
14#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
15#include "src/gpu/glsl/GrGLSLUniformHandler.h"
16#include "src/sksl/SkSLString.h"
17
18class GrProcessor;
19class GrProcessorKeyBuilder;
20class GrGLSLFPBuilder;
21class GrGLSLFPFragmentBuilder;
22
23class GrGLSLFragmentProcessor {
24public:
25 GrGLSLFragmentProcessor() {}
26
27 virtual ~GrGLSLFragmentProcessor() {
28 for (int i = 0; i < fChildProcessors.count(); ++i) {
29 delete fChildProcessors[i];
30 }
31 }
32
33 using UniformHandle = GrGLSLUniformHandler::UniformHandle;
34 using SamplerHandle = GrGLSLUniformHandler::SamplerHandle;
35
36private:
37 /**
38 * This class allows the shader builder to provide each GrGLSLFragmentProcessor 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.
42 */
43 template <typename T, int (GrFragmentProcessor::*COUNT)() const>
44 class BuilderInputProvider {
45 public:
46 BuilderInputProvider(const GrFragmentProcessor* fp, const T* ts) : fFP(fp) , fTs(ts) {}
47
48 const T& operator[] (int i) const {
49 SkASSERT(i >= 0 && i < (fFP->*COUNT)());
50 return fTs[i];
51 }
52
53 int count() const { return (fFP->*COUNT)(); }
54
55 BuilderInputProvider childInputs(int childIdx) const {
56 const GrFragmentProcessor* child = &fFP->childProcessor(childIdx);
57 int numToSkip = 0;
58 for (const auto& fp : GrFragmentProcessor::FPCRange(*fFP)) {
59 if (&fp == child) {
60 return BuilderInputProvider(child, fTs + numToSkip);
61 }
62 numToSkip += (fp.*COUNT)();
63 }
64 SK_ABORT("Didn't find the child.");
65 return {nullptr, nullptr};
66 }
67
68 private:
69 const GrFragmentProcessor* fFP;
70 const T* fTs;
71 };
72
73public:
74 using TransformedCoordVars = BuilderInputProvider<GrGLSLPrimitiveProcessor::TransformVar,
75 &GrFragmentProcessor::numCoordTransforms>;
76 using TextureSamplers =
77 BuilderInputProvider<SamplerHandle, &GrFragmentProcessor::numTextureSamplers>;
78
79 /** 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
83 @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 half4 in the FS in which the stage should place its
88 output color (or coverage).
89 @param inputColor A half4 that holds the input color to the stage in the FS. This may
90 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
93 (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
97 each of the GrFragmentProcessor's GrCoordTransforms.
98 @param texSamplers Contains one entry for each TextureSampler of the GrProcessor.
99 These can be passed to the builder to emit texture reads in the
100 generated code.
101 */
102 struct EmitArgs {
103 EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder,
104 GrGLSLUniformHandler* uniformHandler,
105 const GrShaderCaps* caps,
106 const GrFragmentProcessor& fp,
107 const char* outputColor,
108 const char* inputColor,
109 const TransformedCoordVars& transformedCoordVars,
110 const TextureSamplers& textureSamplers)
111 : fFragBuilder(fragBuilder)
112 , fUniformHandler(uniformHandler)
113 , fShaderCaps(caps)
114 , fFp(fp)
115 , fOutputColor(outputColor)
116 , fInputColor(inputColor ? inputColor : "half4(1.0)")
117 , fTransformedCoords(transformedCoordVars)
118 , fTexSamplers(textureSamplers) {}
119 GrGLSLFPFragmentBuilder* fFragBuilder;
120 GrGLSLUniformHandler* fUniformHandler;
121 const GrShaderCaps* fShaderCaps;
122 const GrFragmentProcessor& fFp;
123 const char* fOutputColor;
124 const char* fInputColor;
125 const TransformedCoordVars& fTransformedCoords;
126 const TextureSamplers& fTexSamplers;
127 };
128
129 virtual void emitCode(EmitArgs&) = 0;
130
131 // This does not recurse to any attached child processors. Recursing the entire processor tree
132 // is the responsibility of the caller.
133 void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor);
134
135 int numChildProcessors() const { return fChildProcessors.count(); }
136
137 GrGLSLFragmentProcessor* childProcessor(int index) const { return fChildProcessors[index]; }
138
139 // Invoke the child with the default input color (solid white)
140 inline SkString invokeChild(int childIndex, EmitArgs& parentArgs,
141 SkSL::String skslCoords = "") {
142 return this->invokeChild(childIndex, nullptr, parentArgs, skslCoords);
143 }
144
145 /** Invokes a child proc in its own scope. Pass in the parent's EmitArgs and invokeChild will
146 * automatically extract the coords and samplers of that child and pass them on to the child's
147 * emitCode(). Also, any uniforms or functions emitted by the child will have their names
148 * mangled to prevent redefinitions. The returned string contains the output color (as a call
149 * to the child's helper function). It is legal to pass nullptr as inputColor, since all
150 * fragment processors are required to work without an input color.
151 */
152 SkString invokeChild(int childIndex, const char* inputColor, EmitArgs& parentArgs,
153 SkSL::String skslCoords = "");
154
155 /**
156 * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of
157 * GLSLFPS. If initialized with an array color followed by coverage processors installed in a
158 * program thenthe iteration order will agree with a GrFragmentProcessor::Iter initialized with
159 * a GrPipeline that produces the same program key.
160 */
161 class Iter {
162 public:
163 Iter(std::unique_ptr<GrGLSLFragmentProcessor> fps[], int cnt);
164
165 GrGLSLFragmentProcessor& operator*() const;
166 GrGLSLFragmentProcessor* operator->() const;
167 Iter& operator++();
168 operator bool() const { return !fFPStack.empty(); }
169
170 // Because each iterator carries a stack we want to avoid copies.
171 Iter(const Iter&) = delete;
172 Iter& operator=(const Iter&) = delete;
173
174 private:
175 SkSTArray<4, GrGLSLFragmentProcessor*, true> fFPStack;
176 };
177
178protected:
179 /** A GrGLSLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces
180 the same stage key; this function reads data from a GrFragmentProcessor and uploads any
181 uniform variables required by the shaders created in emitCode(). The GrFragmentProcessor
182 parameter is guaranteed to be of the same type that created this GrGLSLFragmentProcessor and
183 to have an identical processor key as the one that created this GrGLSLFragmentProcessor. */
184 virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {}
185
186private:
187 // one per child; either not present or empty string if not yet emitted
188 SkTArray<SkString> fFunctionNames;
189
190 SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors;
191
192 friend class GrFragmentProcessor;
193};
194
195#endif
196