Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Public Member Functions | Private 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
 
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)
 

Private Member Functions

void onSetData (const GrGLSLProgramDataManager &pdman, const GrFragmentProcessor &_proc) override
 

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 }
@ kFragment_GrShaderFlag
SkColor4f color
#define SkAssertResult(cond)
Definition SkAssert.h:123
#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)
GrFragmentProcessor * childProcessor(int index)
const SkSL::SampleUsage & sampleUsage() const
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
virtual size_t slotCount() const
Definition SkSLType.h:457
Variable * var() const
const char * c_str() const
Definition SkString.h:133
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
uint8_t value
const char * name
Definition fuchsia.cc:50
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
bool type_to_sksltype(const Context &context, const Type &type, SkSLType *outType)
Definition SkSLUtil.cpp:45
const uint32_t fp
dst
Definition cp.py:12
std::string to_string(float value)
Definition ref_ptr.h:256
static SkString to_string(int n)

◆ onSetData()

void GrSkSLFP::Impl::onSetData ( const GrGLSLProgramDataManager ,
const GrFragmentProcessor  
)
inlineoverrideprivatevirtual

A ProgramImpl instance can be reused with any GrFragmentProcessor that produces the same the same key; this function reads data from a GrFragmentProcessor and uploads any uniform variables required by the shaders created in emitCode(). The GrFragmentProcessor parameter is guaranteed to be of the same type that created this ProgramImpl and to have an identical key as the one that created this ProgramImpl.

Reimplemented from GrFragmentProcessor::ProgramImpl.

Definition at line 277 of file GrSkSLFP.cpp.

278 {
279 const GrSkSLFP& outer = _proc.cast<GrSkSLFP>();
280 pdman.setRuntimeEffectUniforms(outer.fEffect->uniforms(),
281 SkSpan(fUniformHandles),
282 SkSpan(outer.specialized(), outer.uniformCount()),
283 outer.uniformData());
284 }
const T & cast() const
SkSpan< const Uniform > uniforms() const

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