Flutter Engine
The Flutter Engine
Public Member Functions | List of all members
GrSkSLFP::Impl Class Reference
Inheritance diagram for GrSkSLFP::Impl:
GrFragmentProcessor::ProgramImpl

Public Member Functions

void emitCode (EmitArgs &args) override
 
- Public Member Functions inherited from GrFragmentProcessor::ProgramImpl
 ProgramImpl ()=default
 
virtual ~ProgramImpl ()=default
 
virtual void emitCode (EmitArgs &)=0
 
void setData (const GrGLSLProgramDataManager &pdman, const GrFragmentProcessor &processor)
 
int numChildProcessors () const
 
ProgramImplchildProcessor (int index) const
 
void setFunctionName (SkString name)
 
const char * functionName () const
 
SkString invokeChild (int childIndex, EmitArgs &parentArgs, std::string_view skslCoords={})
 
SkString invokeChildWithMatrix (int childIndex, EmitArgs &parentArgs)
 
SkString invokeChild (int childIndex, const char *inputColor, EmitArgs &parentArgs, std::string_view skslCoords={})
 
SkString invokeChildWithMatrix (int childIndex, const char *inputColor, EmitArgs &parentArgs)
 
SkString invokeChild (int childIndex, const char *inputColor, const char *destColor, EmitArgs &parentArgs, std::string_view skslCoords={})
 
SkString invokeChildWithMatrix (int childIndex, const char *inputColor, const char *destColor, EmitArgs &parentArgs)
 

Additional Inherited Members

- Public Types inherited from GrFragmentProcessor::ProgramImpl
using UniformHandle = GrGLSLUniformHandler::UniformHandle
 
using SamplerHandle = GrGLSLUniformHandler::SamplerHandle
 

Detailed Description

Definition at line 50 of file GrSkSLFP.cpp.

Member Function Documentation

◆ emitCode()

void GrSkSLFP::Impl::emitCode ( EmitArgs args)
inlineoverridevirtual

Implements GrFragmentProcessor::ProgramImpl.

Definition at line 52 of file GrSkSLFP.cpp.

52 {
53 const GrSkSLFP& fp = args.fFp.cast<GrSkSLFP>();
54 const SkSL::Program& program = *fp.fEffect->fBaseProgram;
55
56 class FPCallbacks : public SkSL::PipelineStage::Callbacks {
57 public:
58 FPCallbacks(Impl* self,
59 EmitArgs& args,
60 const char* inputColor,
61 const SkSL::Context& context,
62 const uint8_t* uniformData,
63 const Specialized* specialized)
64 : fSelf(self)
65 , fArgs(args)
66 , fInputColor(inputColor)
67 , fContext(context)
68 , fUniformData(uniformData)
69 , fSpecialized(specialized) {}
70
71 std::string declareUniform(const SkSL::VarDeclaration* decl) override {
72 const SkSL::Variable* var = decl->var();
73 if (var->type().isOpaque()) {
74 // Nothing to do. The only opaque types we should see are children, and those
75 // are handled specially.
76 SkASSERT(var->type().isEffectChild());
77 return std::string(var->name());
78 }
79
80 const SkSL::Type* type = &var->type();
81 size_t sizeInBytes = type->slotCount() * sizeof(float);
82 const float* floatData = reinterpret_cast<const float*>(fUniformData);
83 const int* intData = reinterpret_cast<const int*>(fUniformData);
84 fUniformData += sizeInBytes;
85
86 bool isArray = false;
87 if (type->isArray()) {
88 type = &type->componentType();
89 isArray = true;
90 }
91
92 SkSLType gpuType;
94
95 if (*fSpecialized++ == Specialized::kYes) {
96 SkASSERTF(!isArray, "specializing array uniforms is not allowed");
97 std::string value = SkSLTypeString(gpuType);
98 value.append("(");
99
100 bool isFloat = SkSLTypeIsFloatType(gpuType);
101 size_t slots = type->slotCount();
102 for (size_t i = 0; i < slots; ++i) {
103 value.append(isFloat ? skstd::to_string(floatData[i])
104 : std::to_string(intData[i]));
105 value.append(",");
106 }
107 value.back() = ')';
108 return value;
109 }
110
111 const char* uniformName = nullptr;
112 auto handle =
113 fArgs.fUniformHandler->addUniformArray(&fArgs.fFp.cast<GrSkSLFP>(),
115 gpuType,
116 SkString(var->name()).c_str(),
117 isArray ? var->type().columns() : 0,
118 &uniformName);
119 fSelf->fUniformHandles.push_back(handle);
120 return std::string(uniformName);
121 }
122
123 std::string getMangledName(const char* name) override {
124 return std::string(fArgs.fFragBuilder->getMangledFunctionName(name).c_str());
125 }
126
127 void defineFunction(const char* decl, const char* body, bool isMain) override {
128 if (isMain) {
129 fArgs.fFragBuilder->codeAppend(body);
130 } else {
131 fArgs.fFragBuilder->emitFunction(decl, body);
132 }
133 }
134
135 void declareFunction(const char* decl) override {
136 fArgs.fFragBuilder->emitFunctionPrototype(decl);
137 }
138
139 void defineStruct(const char* definition) override {
140 fArgs.fFragBuilder->definitionAppend(definition);
141 }
142
143 void declareGlobal(const char* declaration) override {
144 fArgs.fFragBuilder->definitionAppend(declaration);
145 }
146
147 std::string sampleShader(int index, std::string coords) override {
148 // If the child was sampled using the coords passed to main (and they are never
149 // modified), then we will have marked the child as PassThrough. The code generator
150 // doesn't know that, and still supplies coords. Inside invokeChild, we assert that
151 // any coords passed for a PassThrough child match args.fSampleCoords exactly.
152 //
153 // Normally, this is valid. Here, we *copied* the sample coords to a local variable
154 // (so that they're mutable in the runtime effect SkSL). Thus, the coords string we
155 // get here is the name of the local copy, and fSampleCoords still points to the
156 // unmodified original (which might be a varying, for example).
157 // To prevent the assert, we pass the empty string in this case. Note that for
158 // children sampled like this, invokeChild doesn't even use the coords parameter,
159 // except for that assert.
160 const GrFragmentProcessor* child = fArgs.fFp.childProcessor(index);
161 if (child && child->sampleUsage().isPassThrough()) {
162 coords.clear();
163 }
164 return child ? std::string(fSelf->invokeChild(index, fInputColor, fArgs, coords)
165 .c_str())
166 : std::string("half4(0)");
167 }
168
169 std::string sampleColorFilter(int index, std::string color) override {
170 return std::string(fSelf->invokeChild(index,
171 color.empty() ? fInputColor : color.c_str(),
172 fArgs)
173 .c_str());
174 }
175
176 std::string sampleBlender(int index, std::string src, std::string dst) override {
177 if (!fSelf->childProcessor(index)) {
178 return SkSL::String::printf("blend_src_over(%s, %s)", src.c_str(), dst.c_str());
179 }
180 return std::string(
181 fSelf->invokeChild(index, src.c_str(), dst.c_str(), fArgs).c_str());
182 }
183
184 // These intrinsics take and return 3-component vectors, but child FPs operate on
185 // 4-component vectors. We use swizzles here to paper over the difference.
186 std::string toLinearSrgb(std::string color) override {
187 const GrSkSLFP& fp = fArgs.fFp.cast<GrSkSLFP>();
188 if (fp.fToLinearSrgbChildIndex < 0) {
189 return color;
190 }
191 color = SkSL::String::printf("(%s).rgb1", color.c_str());
192 SkString xformedColor = fSelf->invokeChild(
193 fp.fToLinearSrgbChildIndex, color.c_str(), fArgs);
194 return SkSL::String::printf("(%s).rgb", xformedColor.c_str());
195 }
196
197 std::string fromLinearSrgb(std::string color) override {
198 const GrSkSLFP& fp = fArgs.fFp.cast<GrSkSLFP>();
199 if (fp.fFromLinearSrgbChildIndex < 0) {
200 return color;
201 }
202 color = SkSL::String::printf("(%s).rgb1", color.c_str());
203 SkString xformedColor = fSelf->invokeChild(
204 fp.fFromLinearSrgbChildIndex, color.c_str(), fArgs);
205 return SkSL::String::printf("(%s).rgb", xformedColor.c_str());
206 }
207
208 Impl* fSelf;
209 EmitArgs& fArgs;
210 const char* fInputColor;
211 const SkSL::Context& fContext;
212 const uint8_t* fUniformData;
213 const Specialized* fSpecialized;
214 int fUniformIndex = 0;
215 };
216
217 // If we have an input child, we invoke it now, and make the result of that be the "input
218 // color" for all other purposes later (eg, the default passed via sample calls, etc.)
219 if (fp.fInputChildIndex >= 0) {
220 args.fFragBuilder->codeAppendf("%s = %s;\n",
221 args.fInputColor,
222 this->invokeChild(fp.fInputChildIndex, args).c_str());
223 }
224
225 if (fp.fEffect->allowBlender()) {
226 // If we have an dest-color child, we invoke it now, and make the result of that be the
227 // "dest color" for all other purposes later.
228 if (fp.fDestColorChildIndex >= 0) {
229 args.fFragBuilder->codeAppendf(
230 "%s = %s;\n",
231 args.fDestColor,
232 this->invokeChild(fp.fDestColorChildIndex, args.fDestColor, args).c_str());
233 }
234 } else {
235 // We're not making a blender, so we don't expect a dest-color child FP to exist.
236 SkASSERT(fp.fDestColorChildIndex < 0);
237 }
238
239 // Snap off a global copy of the input color at the start of main. We need this when
240 // we call child processors (particularly from helper functions, which can't "see" the
241 // parameter to main). Even from within main, if the code mutates the parameter, calls to
242 // sample should still be passing the original color (by default).
243 SkString inputColorName;
244 if (fp.fEffect->samplesOutsideMain()) {
245 GrShaderVar inputColorCopy(args.fFragBuilder->getMangledFunctionName("inColor"),
247 args.fFragBuilder->declareGlobal(inputColorCopy);
248 inputColorName = inputColorCopy.getName();
249 args.fFragBuilder->codeAppendf("%s = %s;\n", inputColorName.c_str(), args.fInputColor);
250 } else {
251 inputColorName = args.fFragBuilder->newTmpVarName("inColor");
252 args.fFragBuilder->codeAppendf(
253 "half4 %s = %s;\n", inputColorName.c_str(), args.fInputColor);
254 }
255
256 // Copy the incoming coords to a local variable. Code in main might modify the coords
257 // parameter. fSampleCoord could be a varying, so writes to it would be illegal.
258 const char* coords = "float2(0)";
259 SkString coordsVarName;
260 if (fp.usesSampleCoordsDirectly()) {
261 coordsVarName = args.fFragBuilder->newTmpVarName("coords");
262 coords = coordsVarName.c_str();
263 args.fFragBuilder->codeAppendf("float2 %s = %s;\n", coords, args.fSampleCoord);
264 }
265
266 FPCallbacks callbacks(this,
267 args,
268 inputColorName.c_str(),
269 *program.fContext,
270 fp.uniformData(),
271 fp.specialized());
273 program, coords, args.fInputColor, args.fDestColor, &callbacks);
274 }
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
@ kFragment_GrShaderFlag
Definition: GrTypesPriv.h:287
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define SkASSERTF(cond, fmt,...)
Definition: SkAssert.h:117
const Context & fContext
const char * SkSLTypeString(SkSLType t)
SkSLType
static constexpr bool SkSLTypeIsFloatType(SkSLType type)
GLenum type
GrFragmentProcessor * childProcessor(int index)
const SkSL::SampleUsage & sampleUsage() const
const char * name() const override
Definition: GrSkSLFP.h:186
bool isPassThrough() const
std::string_view name() const
Definition: SkSLSymbol.h:51
const Type & type() const
Definition: SkSLSymbol.h:42
bool isEffectChild() const
Definition: SkSLType.h:550
bool isOpaque() const
Definition: SkSLType.h:353
virtual int columns() const
Definition: SkSLType.h:429
Variable * var() const
const char * c_str() const
Definition: SkString.h:133
DlColor color
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
uint8_t value
void ConvertProgram(const Program &program, const char *sampleCoords, const char *inputColor, const char *destColor, Callbacks *callbacks)
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: SkSLString.cpp:83
bool type_to_sksltype(const Context &context, const Type &type, SkSLType *outType)
Definition: SkSLUtil.cpp:46
const uint32_t fp
dst
Definition: cp.py:12
std::string to_string(float value)
Definition: SkSLString.cpp:50
Definition: ref_ptr.h:256
static SkString to_string(int n)
Definition: nanobench.cpp:119

The documentation for this class was generated from the following file: