1 /*
2 * Copyright 2016 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 #include "SkSLCPPCodeGenerator.h"
9
10 #include "SkSLCompiler.h"
11 #include "SkSLHCodeGenerator.h"
12
13 namespace SkSL {
14
needs_uniform_var(const Variable & var)15 static bool needs_uniform_var(const Variable& var) {
16 return (var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
17 strcmp(var.fType.fName.c_str(), "colorSpaceXform");
18 }
19
CPPCodeGenerator(const Context * context,const Program * program,ErrorReporter * errors,String name,OutputStream * out)20 CPPCodeGenerator::CPPCodeGenerator(const Context* context, const Program* program,
21 ErrorReporter* errors, String name, OutputStream* out)
22 : INHERITED(context, program, errors, out)
23 , fName(std::move(name))
24 , fFullName(String::printf("Gr%s", fName.c_str()))
25 , fSectionAndParameterHelper(*program, *errors) {
26 fLineEnding = "\\n";
27 }
28
writef(const char * s,va_list va)29 void CPPCodeGenerator::writef(const char* s, va_list va) {
30 static constexpr int BUFFER_SIZE = 1024;
31 va_list copy;
32 va_copy(copy, va);
33 char buffer[BUFFER_SIZE];
34 int length = vsnprintf(buffer, BUFFER_SIZE, s, va);
35 if (length < BUFFER_SIZE) {
36 fOut->write(buffer, length);
37 } else {
38 std::unique_ptr<char[]> heap(new char[length + 1]);
39 vsprintf(heap.get(), s, copy);
40 fOut->write(heap.get(), length);
41 }
42 }
43
writef(const char * s,...)44 void CPPCodeGenerator::writef(const char* s, ...) {
45 va_list va;
46 va_start(va, s);
47 this->writef(s, va);
48 va_end(va);
49 }
50
writeHeader()51 void CPPCodeGenerator::writeHeader() {
52 }
53
writePrecisionModifier()54 void CPPCodeGenerator::writePrecisionModifier() {
55 }
56
writeBinaryExpression(const BinaryExpression & b,Precedence parentPrecedence)57 void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
58 Precedence parentPrecedence) {
59 if (b.fOperator == Token::PERCENT) {
60 // need to use "%%" instead of "%" b/c the code will be inside of a printf
61 Precedence precedence = GetBinaryPrecedence(b.fOperator);
62 if (precedence >= parentPrecedence) {
63 this->write("(");
64 }
65 this->writeExpression(*b.fLeft, precedence);
66 this->write(" %% ");
67 this->writeExpression(*b.fRight, precedence);
68 if (precedence >= parentPrecedence) {
69 this->write(")");
70 }
71 } else {
72 INHERITED::writeBinaryExpression(b, parentPrecedence);
73 }
74 }
75
writeIndexExpression(const IndexExpression & i)76 void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) {
77 const Expression& base = *i.fBase;
78 if (base.fKind == Expression::kVariableReference_Kind) {
79 int builtin = ((VariableReference&) base).fVariable.fModifiers.fLayout.fBuiltin;
80 if (SK_TRANSFORMEDCOORDS2D_BUILTIN == builtin) {
81 this->write("%s");
82 if (i.fIndex->fKind != Expression::kIntLiteral_Kind) {
83 fErrors.error(i.fIndex->fPosition,
84 "index into sk_TransformedCoords2D must be an integer literal");
85 return;
86 }
87 int64_t index = ((IntLiteral&) *i.fIndex).fValue;
88 String name = "sk_TransformedCoords2D_" + to_string(index);
89 fFormatArgs.push_back(name + ".c_str()");
90 if (fWrittenTransformedCoords.find(index) == fWrittenTransformedCoords.end()) {
91 fExtraEmitCodeCode += " SkSL::String " + name +
92 " = fragBuilder->ensureCoords2D(args.fTransformedCoords[" +
93 to_string(index) + "]);\n";
94 fWrittenTransformedCoords.insert(index);
95 }
96 return;
97 } else if (SK_TEXTURESAMPLERS_BUILTIN == builtin) {
98 this->write("%s");
99 if (i.fIndex->fKind != Expression::kIntLiteral_Kind) {
100 fErrors.error(i.fIndex->fPosition,
101 "index into sk_TextureSamplers must be an integer literal");
102 return;
103 }
104 int64_t index = ((IntLiteral&) *i.fIndex).fValue;
105 fFormatArgs.push_back(" fragBuilder->getProgramBuilder()->samplerVariable("
106 "args.fTexSamplers[" + to_string(index) + "]).c_str()");
107 return;
108 }
109 }
110 INHERITED::writeIndexExpression(i);
111 }
112
default_value(const Type & type)113 static const char* default_value(const Type& type) {
114 const char* name = type.name().c_str();
115 if (!strcmp(name, "float")) {
116 return "0.0";
117 } else if (!strcmp(name, "vec2")) {
118 return "vec2(0.0)";
119 } else if (!strcmp(name, "vec3")) {
120 return "vec3(0.0)";
121 } else if (!strcmp(name, "vec4")) {
122 return "vec4(0.0)";
123 } else if (!strcmp(name, "mat4") || !strcmp(name, "colorSpaceXform")) {
124 return "mat4(1.0)";
125 }
126 ABORT("unsupported default_value type\n");
127 }
128
is_private(const Variable & var)129 static bool is_private(const Variable& var) {
130 return !(var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
131 !(var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
132 var.fStorage == Variable::kGlobal_Storage &&
133 var.fModifiers.fLayout.fBuiltin == -1;
134 }
135
writeRuntimeValue(const Type & type,const String & cppCode)136 void CPPCodeGenerator::writeRuntimeValue(const Type& type, const String& cppCode) {
137 if (type == *fContext.fFloat_Type) {
138 this->write("%f");
139 fFormatArgs.push_back(cppCode);
140 } else if (type == *fContext.fInt_Type) {
141 this->write("%d");
142 fFormatArgs.push_back(cppCode);
143 } else if (type == *fContext.fBool_Type) {
144 this->write("%s");
145 fFormatArgs.push_back("(" + cppCode + " ? \"true\" : \"false\")");
146 } else if (type == *fContext.fVec2_Type) {
147 this->write("vec2(%f, %f)");
148 fFormatArgs.push_back(cppCode + ".fX");
149 fFormatArgs.push_back(cppCode + ".fY");
150 } else {
151 printf("%s\n", type.name().c_str());
152 ABORT("unsupported runtime value type\n");
153 }
154 }
155
writeVarInitializer(const Variable & var,const Expression & value)156 void CPPCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
157 if (is_private(var)) {
158 this->writeRuntimeValue(var.fType, var.fName);
159 } else {
160 this->writeExpression(value, kTopLevel_Precedence);
161 }
162 }
163
getSamplerHandle(const Variable & var)164 String CPPCodeGenerator::getSamplerHandle(const Variable& var) {
165 int samplerCount = 0;
166 for (const auto param : fSectionAndParameterHelper.getParameters()) {
167 if (&var == param) {
168 return "args.fTexSamplers[" + to_string(samplerCount) + "]";
169 }
170 if (param->fType.kind() == Type::kSampler_Kind) {
171 ++samplerCount;
172 }
173 }
174 ABORT("should have found sampler in parameters\n");
175 }
176
writeVariableReference(const VariableReference & ref)177 void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
178 switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
179 case SK_INCOLOR_BUILTIN:
180 this->write("%s");
181 fFormatArgs.push_back(String("args.fInputColor ? args.fInputColor : \"vec4(1)\""));
182 break;
183 case SK_OUTCOLOR_BUILTIN:
184 this->write("%s");
185 fFormatArgs.push_back(String("args.fOutputColor"));
186 break;
187 default:
188 if (ref.fVariable.fType.kind() == Type::kSampler_Kind) {
189 this->write("%s");
190 fFormatArgs.push_back("fragBuilder->getProgramBuilder()->samplerVariable(" +
191 this->getSamplerHandle(ref.fVariable) + ").c_str()");
192 return;
193 }
194 if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) {
195 this->write("%s");
196 String name = ref.fVariable.fName;
197 String var;
198 if (ref.fVariable.fType == *fContext.fColorSpaceXform_Type) {
199 ASSERT(fNeedColorSpaceHelper);
200 var = String::printf("fColorSpaceHelper.isValid() ? "
201 "args.fUniformHandler->getUniformCStr("
202 "fColorSpaceHelper.gamutXformUniform()) : \"%s\"",
203 default_value(ref.fVariable.fType));
204 } else {
205 var = String::printf("args.fUniformHandler->getUniformCStr(%sVar)",
206 HCodeGenerator::FieldName(name.c_str()).c_str());
207 }
208 String code;
209 if (ref.fVariable.fModifiers.fLayout.fWhen.size()) {
210 code = String::printf("%sVar.isValid() ? %s : \"%s\"",
211 HCodeGenerator::FieldName(name.c_str()).c_str(),
212 var.c_str(),
213 default_value(ref.fVariable.fType));
214 } else {
215 code = var;
216 }
217 fFormatArgs.push_back(code);
218 } else if (SectionAndParameterHelper::IsParameter(ref.fVariable)) {
219 const char* name = ref.fVariable.fName.c_str();
220 this->writeRuntimeValue(ref.fVariable.fType,
221 String::printf("_outer.%s()", name).c_str());
222 } else {
223 this->write(ref.fVariable.fName.c_str());
224 }
225 }
226 }
227
writeIfStatement(const IfStatement & s)228 void CPPCodeGenerator::writeIfStatement(const IfStatement& s) {
229 if (s.fIsStatic) {
230 this->write("@");
231 }
232 INHERITED::writeIfStatement(s);
233 }
234
writeSwitchStatement(const SwitchStatement & s)235 void CPPCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
236 if (s.fIsStatic) {
237 this->write("@");
238 }
239 INHERITED::writeSwitchStatement(s);
240 }
241
writeFunctionCall(const FunctionCall & c)242 void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
243 if (c.fFunction.fBuiltin && c.fFunction.fName == "COLORSPACE") {
244 String tmpVar = "_tmpVar" + to_string(++fVarCount);
245 fFunctionHeader += "vec4 " + tmpVar + ";";
246 ASSERT(c.fArguments.size() == 2);
247 this->write("%s");
248 fFormatArgs.push_back("fColorSpaceHelper.isValid() ? \"(" + tmpVar + " = \" : \"\"");
249 this->writeExpression(*c.fArguments[0], kTopLevel_Precedence);
250 ASSERT(c.fArguments[1]->fKind == Expression::kVariableReference_Kind);
251 String xform("args.fUniformHandler->getUniformCStr(fColorSpaceHelper.gamutXformUniform())");
252 this->write("%s");
253 fFormatArgs.push_back("fColorSpaceHelper.isValid() ? SkStringPrintf(\", vec4(clamp((%s * vec4(" + tmpVar + ".rgb, 1.0)).rgb, 0.0, " + tmpVar +
254 ".a), " + tmpVar + ".a))\", " + xform + ").c_str() : \"\"");
255 return;
256 }
257 INHERITED::writeFunctionCall(c);
258 if (c.fFunction.fBuiltin && c.fFunction.fName == "texture") {
259 this->write(".%s");
260 ASSERT(c.fArguments.size() >= 1);
261 ASSERT(c.fArguments[0]->fKind == Expression::kVariableReference_Kind);
262 String sampler = this->getSamplerHandle(((VariableReference&) *c.fArguments[0]).fVariable);
263 fFormatArgs.push_back("fragBuilder->getProgramBuilder()->samplerSwizzle(" + sampler +
264 ").c_str()");
265 }
266 }
267
writeFunction(const FunctionDefinition & f)268 void CPPCodeGenerator::writeFunction(const FunctionDefinition& f) {
269 if (f.fDeclaration.fName == "main") {
270 fFunctionHeader = "";
271 OutputStream* oldOut = fOut;
272 StringStream buffer;
273 fOut = &buffer;
274 for (const auto& s : ((Block&) *f.fBody).fStatements) {
275 this->writeStatement(*s);
276 this->writeLine();
277 }
278
279 fOut = oldOut;
280 this->write(fFunctionHeader);
281 this->write(buffer.str());
282 } else {
283 INHERITED::writeFunction(f);
284 }
285 }
286
writeSetting(const Setting & s)287 void CPPCodeGenerator::writeSetting(const Setting& s) {
288 static constexpr const char* kPrefix = "sk_Args.";
289 if (!strncmp(s.fName.c_str(), kPrefix, strlen(kPrefix))) {
290 const char* name = s.fName.c_str() + strlen(kPrefix);
291 this->writeRuntimeValue(s.fType, HCodeGenerator::FieldName(name).c_str());
292 } else {
293 this->write(s.fName.c_str());
294 }
295 }
296
writeSection(const char * name,const char * prefix)297 void CPPCodeGenerator::writeSection(const char* name, const char* prefix) {
298 const Section* s = fSectionAndParameterHelper.getSection(name);
299 if (s) {
300 this->writef("%s%s", prefix, s->fText.c_str());
301 }
302 }
303
writeProgramElement(const ProgramElement & p)304 void CPPCodeGenerator::writeProgramElement(const ProgramElement& p) {
305 if (p.fKind == ProgramElement::kSection_Kind) {
306 return;
307 }
308 if (p.fKind == ProgramElement::kVar_Kind) {
309 const VarDeclarations& decls = (const VarDeclarations&) p;
310 if (!decls.fVars.size()) {
311 return;
312 }
313 const Variable& var = *((VarDeclaration&) *decls.fVars[0]).fVar;
314 if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) ||
315 -1 != var.fModifiers.fLayout.fBuiltin) {
316 return;
317 }
318 }
319 INHERITED::writeProgramElement(p);
320 }
321
addUniform(const Variable & var)322 void CPPCodeGenerator::addUniform(const Variable& var) {
323 if (!needs_uniform_var(var)) {
324 return;
325 }
326 const char* precision;
327 if (var.fModifiers.fFlags & Modifiers::kHighp_Flag) {
328 precision = "kHigh_GrSLPrecision";
329 } else if (var.fModifiers.fFlags & Modifiers::kMediump_Flag) {
330 precision = "kMedium_GrSLPrecision";
331 } else if (var.fModifiers.fFlags & Modifiers::kLowp_Flag) {
332 precision = "kLow_GrSLPrecision";
333 } else {
334 precision = "kDefault_GrSLPrecision";
335 }
336 const char* type;
337 if (var.fType == *fContext.fFloat_Type) {
338 type = "kFloat_GrSLType";
339 } else if (var.fType == *fContext.fVec2_Type) {
340 type = "kVec2f_GrSLType";
341 } else if (var.fType == *fContext.fVec4_Type) {
342 type = "kVec4f_GrSLType";
343 } else if (var.fType == *fContext.fMat4x4_Type ||
344 var.fType == *fContext.fColorSpaceXform_Type) {
345 type = "kMat44f_GrSLType";
346 } else {
347 ABORT("unsupported uniform type: %s %s;\n", var.fType.name().c_str(), var.fName.c_str());
348 }
349 if (var.fModifiers.fLayout.fWhen.size()) {
350 this->writef(" if (%s) {\n ", var.fModifiers.fLayout.fWhen.c_str());
351 }
352 const char* name = var.fName.c_str();
353 this->writef(" %sVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, %s, "
354 "%s, \"%s\");\n", HCodeGenerator::FieldName(name).c_str(), type, precision, name);
355 if (var.fModifiers.fLayout.fWhen.size()) {
356 this->write(" }\n");
357 }
358 }
359
writePrivateVars()360 void CPPCodeGenerator::writePrivateVars() {
361 for (const auto& p : fProgram.fElements) {
362 if (ProgramElement::kVar_Kind == p->fKind) {
363 const VarDeclarations* decls = (const VarDeclarations*) p.get();
364 for (const auto& raw : decls->fVars) {
365 VarDeclaration& decl = (VarDeclaration&) *raw;
366 if (is_private(*decl.fVar)) {
367 this->writef("%s %s;\n",
368 HCodeGenerator::FieldType(decl.fVar->fType).c_str(),
369 decl.fVar->fName.c_str());
370 }
371 }
372 }
373 }
374 }
375
writePrivateVarValues()376 void CPPCodeGenerator::writePrivateVarValues() {
377 for (const auto& p : fProgram.fElements) {
378 if (ProgramElement::kVar_Kind == p->fKind) {
379 const VarDeclarations* decls = (const VarDeclarations*) p.get();
380 for (const auto& raw : decls->fVars) {
381 VarDeclaration& decl = (VarDeclaration&) *raw;
382 if (is_private(*decl.fVar) && decl.fValue) {
383 this->writef("%s = %s;\n",
384 decl.fVar->fName.c_str(),
385 decl.fValue->description().c_str());
386 }
387 }
388 }
389 }
390 }
391
writeEmitCode(std::vector<const Variable * > & uniforms)392 bool CPPCodeGenerator::writeEmitCode(std::vector<const Variable*>& uniforms) {
393 this->write(" void emitCode(EmitArgs& args) override {\n"
394 " GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n");
395 this->writef(" const %s& _outer = args.fFp.cast<%s>();\n"
396 " (void) _outer;\n",
397 fFullName.c_str(), fFullName.c_str());
398 this->writePrivateVarValues();
399 for (const auto u : uniforms) {
400 this->addUniform(*u);
401 if (u->fType == *fContext.fColorSpaceXform_Type) {
402 if (fNeedColorSpaceHelper) {
403 fErrors.error(u->fPosition, "only a single ColorSpaceXform is supported");
404 }
405 fNeedColorSpaceHelper = true;
406 this->writef(" fColorSpaceHelper.emitCode(args.fUniformHandler, "
407 "_outer.%s().get());\n",
408 u->fName.c_str());
409 }
410 }
411 this->writeSection(EMIT_CODE_SECTION);
412 OutputStream* old = fOut;
413 StringStream mainBuffer;
414 fOut = &mainBuffer;
415 bool result = INHERITED::generateCode();
416 fOut = old;
417 this->writef("%s fragBuilder->codeAppendf(\"%s\"", fExtraEmitCodeCode.c_str(),
418 mainBuffer.str().c_str());
419 for (const auto& s : fFormatArgs) {
420 this->writef(", %s", s.c_str());
421 }
422 this->write(");\n"
423 " }\n");
424 return result;
425 }
426
writeSetData(std::vector<const Variable * > & uniforms)427 void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
428 const char* fullName = fFullName.c_str();
429 const Section* section = fSectionAndParameterHelper.getSection(SET_DATA_SECTION);
430 const char* pdman = section ? section->fArgument.c_str() : "pdman";
431 this->writef(" void onSetData(const GrGLSLProgramDataManager& %s, "
432 "const GrFragmentProcessor& _proc) override {\n",
433 pdman);
434 bool wroteProcessor = false;
435 for (const auto u : uniforms) {
436 if (u->fModifiers.fFlags & Modifiers::kIn_Flag) {
437 if (!wroteProcessor) {
438 this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName, fullName);
439 wroteProcessor = true;
440 this->writef(" {\n");
441 }
442 const char* name = u->fName.c_str();
443 if (u->fType == *fContext.fVec4_Type) {
444 this->writef(" const SkRect %sValue = _outer.%s();\n"
445 " %s.set4fv(%sVar, 1, (float*) &%sValue);\n",
446 name, name, pdman, HCodeGenerator::FieldName(name).c_str(), name);
447 } else if (u->fType == *fContext.fMat4x4_Type) {
448 this->writef(" float %sValue[16];\n"
449 " _outer.%s().asColMajorf(%sValue);\n"
450 " %s.setMatrix4f(%sVar, %sValue);\n",
451 name, name, name, pdman, HCodeGenerator::FieldName(name).c_str(),
452 name);
453 } else if (u->fType == *fContext.fColorSpaceXform_Type) {
454 ASSERT(fNeedColorSpaceHelper);
455 this->writef(" if (fColorSpaceHelper.isValid()) {\n"
456 " fColorSpaceHelper.setData(%s, _outer.%s().get());\n"
457 " }\n",
458 pdman, name);
459 } else {
460 this->writef(" %s.set1f(%sVar, _outer.%s());\n",
461 pdman, HCodeGenerator::FieldName(name).c_str(), name);
462 }
463 }
464 }
465 if (wroteProcessor) {
466 this->writef(" }\n");
467 }
468 if (section) {
469 for (const auto& p : fProgram.fElements) {
470 if (ProgramElement::kVar_Kind == p->fKind) {
471 const VarDeclarations* decls = (const VarDeclarations*) p.get();
472 for (const auto& raw : decls->fVars) {
473 VarDeclaration& decl = (VarDeclaration&) *raw;
474 if (needs_uniform_var(*decl.fVar)) {
475 const char* name = decl.fVar->fName.c_str();
476 this->writef(" UniformHandle& %s = %sVar;\n"
477 " (void) %s;\n",
478 name, HCodeGenerator::FieldName(name).c_str(), name);
479 } else if (SectionAndParameterHelper::IsParameter(*decl.fVar)) {
480 const char* name = decl.fVar->fName.c_str();
481 if (!wroteProcessor) {
482 this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName,
483 fullName);
484 wroteProcessor = true;
485 }
486 this->writef(" auto %s = _outer.%s();\n"
487 " (void) %s;\n",
488 name, name, name);
489 }
490 }
491 }
492 }
493 this->writeSection(SET_DATA_SECTION);
494 }
495 this->write(" }\n");
496 }
497
writeTest()498 void CPPCodeGenerator::writeTest() {
499 const Section* test = fSectionAndParameterHelper.getSection(TEST_CODE_SECTION);
500 if (test) {
501 this->writef("GR_DEFINE_FRAGMENT_PROCESSOR_TEST(%s);\n"
502 "#if GR_TEST_UTILS\n"
503 "sk_sp<GrFragmentProcessor> %s::TestCreate(GrProcessorTestData* %s) {\n",
504 fFullName.c_str(),
505 fFullName.c_str(),
506 test->fArgument.c_str());
507 this->writeSection(TEST_CODE_SECTION);
508 this->write("}\n"
509 "#endif\n");
510 }
511 }
512
writeGetKey()513 void CPPCodeGenerator::writeGetKey() {
514 this->writef("void %s::onGetGLSLProcessorKey(const GrShaderCaps& caps, "
515 "GrProcessorKeyBuilder* b) const {\n",
516 fFullName.c_str());
517 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
518 const char* name = param->fName.c_str();
519 if (param->fType == *fContext.fColorSpaceXform_Type) {
520 this->writef(" b->add32(GrColorSpaceXform::XformKey(%s.get()));\n",
521 HCodeGenerator::FieldName(name).c_str());
522 continue;
523 }
524 if (param->fModifiers.fLayout.fKey != Layout::kNo_Key &&
525 (param->fModifiers.fFlags & Modifiers::kUniform_Flag)) {
526 fErrors.error(param->fPosition,
527 "layout(key) may not be specified on uniforms");
528 }
529 switch (param->fModifiers.fLayout.fKey) {
530 case Layout::kKey_Key:
531 if (param->fType == *fContext.fMat4x4_Type) {
532 ABORT("no automatic key handling for mat4\n");
533 } else if (param->fType == *fContext.fVec2_Type) {
534 this->writef(" b->add32(%s.fX);\n",
535 HCodeGenerator::FieldName(name).c_str());
536 this->writef(" b->add32(%s.fY);\n",
537 HCodeGenerator::FieldName(name).c_str());
538 } else if (param->fType == *fContext.fVec4_Type) {
539 this->writef(" b->add32(%s.x());\n",
540 HCodeGenerator::FieldName(name).c_str());
541 this->writef(" b->add32(%s.y());\n",
542 HCodeGenerator::FieldName(name).c_str());
543 this->writef(" b->add32(%s.width());\n",
544 HCodeGenerator::FieldName(name).c_str());
545 this->writef(" b->add32(%s.height());\n",
546 HCodeGenerator::FieldName(name).c_str());
547 } else {
548 this->writef(" b->add32(%s);\n",
549 HCodeGenerator::FieldName(name).c_str());
550 }
551 break;
552 case Layout::kIdentity_Key:
553 if (param->fType.kind() != Type::kMatrix_Kind) {
554 fErrors.error(param->fPosition,
555 "layout(key=identity) requires matrix type");
556 }
557 this->writef(" b->add32(%s.isIdentity() ? 1 : 0);\n",
558 HCodeGenerator::FieldName(name).c_str());
559 break;
560 case Layout::kNo_Key:
561 break;
562 }
563 }
564 this->write("}\n");
565 }
566
generateCode()567 bool CPPCodeGenerator::generateCode() {
568 std::vector<const Variable*> uniforms;
569 for (const auto& p : fProgram.fElements) {
570 if (ProgramElement::kVar_Kind == p->fKind) {
571 const VarDeclarations* decls = (const VarDeclarations*) p.get();
572 for (const auto& raw : decls->fVars) {
573 VarDeclaration& decl = (VarDeclaration&) *raw;
574 if ((decl.fVar->fModifiers.fFlags & Modifiers::kUniform_Flag) &&
575 decl.fVar->fType.kind() != Type::kSampler_Kind) {
576 uniforms.push_back(decl.fVar);
577 }
578 }
579 }
580 }
581 const char* baseName = fName.c_str();
582 const char* fullName = fFullName.c_str();
583 this->writef(kFragmentProcessorHeader, fullName);
584 this->writef("#include \"%s.h\"\n"
585 "#if SK_SUPPORT_GPU\n", fullName);
586 this->writeSection(CPP_SECTION);
587 this->writef("#include \"glsl/GrGLSLColorSpaceXformHelper.h\"\n"
588 "#include \"glsl/GrGLSLFragmentProcessor.h\"\n"
589 "#include \"glsl/GrGLSLFragmentShaderBuilder.h\"\n"
590 "#include \"glsl/GrGLSLProgramBuilder.h\"\n"
591 "#include \"SkSLCPP.h\"\n"
592 "#include \"SkSLUtil.h\"\n"
593 "class GrGLSL%s : public GrGLSLFragmentProcessor {\n"
594 "public:\n"
595 " GrGLSL%s() {}\n",
596 baseName, baseName);
597 bool result = this->writeEmitCode(uniforms);
598 this->write("private:\n");
599 this->writeSetData(uniforms);
600 this->writePrivateVars();
601 for (const auto& u : uniforms) {
602 const char* name = u->fName.c_str();
603 if (needs_uniform_var(*u) && !(u->fModifiers.fFlags & Modifiers::kIn_Flag)) {
604 this->writef(" UniformHandle %sVar;\n", HCodeGenerator::FieldName(name).c_str());
605 }
606 }
607 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
608 const char* name = param->fName.c_str();
609 if (needs_uniform_var(*param)) {
610 this->writef(" UniformHandle %sVar;\n", HCodeGenerator::FieldName(name).c_str());
611 }
612 }
613 if (fNeedColorSpaceHelper) {
614 this->write(" GrGLSLColorSpaceXformHelper fColorSpaceHelper;\n");
615 }
616 this->writef("};\n"
617 "GrGLSLFragmentProcessor* %s::onCreateGLSLInstance() const {\n"
618 " return new GrGLSL%s();\n"
619 "}\n",
620 fullName, baseName);
621 this->writeGetKey();
622 this->writef("bool %s::onIsEqual(const GrFragmentProcessor& other) const {\n"
623 " const %s& that = other.cast<%s>();\n"
624 " (void) that;\n",
625 fullName, fullName, fullName);
626 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
627 const char* name = param->fName.c_str();
628 this->writef(" if (%s != that.%s) return false;\n",
629 HCodeGenerator::FieldName(name).c_str(),
630 HCodeGenerator::FieldName(name).c_str());
631 }
632 this->write(" return true;\n"
633 "}\n");
634 this->writeTest();
635 this->writeSection(CPP_END_SECTION);
636 this->write("#endif\n");
637 result &= 0 == fErrors.errorCount();
638 return result;
639 }
640
641 } // namespace
642