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 var.fType.kind() != Type::kSampler_Kind;
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
usesPrecisionModifiers() const54 bool CPPCodeGenerator::usesPrecisionModifiers() const {
55 return false;
56 }
57
getTypeName(const Type & type)58 String CPPCodeGenerator::getTypeName(const Type& type) {
59 return type.name();
60 }
61
writeBinaryExpression(const BinaryExpression & b,Precedence parentPrecedence)62 void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
63 Precedence parentPrecedence) {
64 if (b.fOperator == Token::PERCENT) {
65 // need to use "%%" instead of "%" b/c the code will be inside of a printf
66 Precedence precedence = GetBinaryPrecedence(b.fOperator);
67 if (precedence >= parentPrecedence) {
68 this->write("(");
69 }
70 this->writeExpression(*b.fLeft, precedence);
71 this->write(" %% ");
72 this->writeExpression(*b.fRight, precedence);
73 if (precedence >= parentPrecedence) {
74 this->write(")");
75 }
76 } else {
77 INHERITED::writeBinaryExpression(b, parentPrecedence);
78 }
79 }
80
writeIndexExpression(const IndexExpression & i)81 void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) {
82 const Expression& base = *i.fBase;
83 if (base.fKind == Expression::kVariableReference_Kind) {
84 int builtin = ((VariableReference&) base).fVariable.fModifiers.fLayout.fBuiltin;
85 if (SK_TRANSFORMEDCOORDS2D_BUILTIN == builtin) {
86 this->write("%s");
87 if (i.fIndex->fKind != Expression::kIntLiteral_Kind) {
88 fErrors.error(i.fIndex->fOffset,
89 "index into sk_TransformedCoords2D must be an integer literal");
90 return;
91 }
92 int64_t index = ((IntLiteral&) *i.fIndex).fValue;
93 String name = "sk_TransformedCoords2D_" + to_string(index);
94 fFormatArgs.push_back(name + ".c_str()");
95 if (fWrittenTransformedCoords.find(index) == fWrittenTransformedCoords.end()) {
96 fExtraEmitCodeCode += " SkString " + name +
97 " = fragBuilder->ensureCoords2D(args.fTransformedCoords[" +
98 to_string(index) + "]);\n";
99 fWrittenTransformedCoords.insert(index);
100 }
101 return;
102 } else if (SK_TEXTURESAMPLERS_BUILTIN == builtin) {
103 this->write("%s");
104 if (i.fIndex->fKind != Expression::kIntLiteral_Kind) {
105 fErrors.error(i.fIndex->fOffset,
106 "index into sk_TextureSamplers must be an integer literal");
107 return;
108 }
109 int64_t index = ((IntLiteral&) *i.fIndex).fValue;
110 fFormatArgs.push_back(" fragBuilder->getProgramBuilder()->samplerVariable("
111 "args.fTexSamplers[" + to_string(index) + "]).c_str()");
112 return;
113 }
114 }
115 INHERITED::writeIndexExpression(i);
116 }
117
default_value(const Type & type)118 static String default_value(const Type& type) {
119 if (type.fName == "bool") {
120 return "false";
121 }
122 switch (type.kind()) {
123 case Type::kScalar_Kind: return "0";
124 case Type::kVector_Kind: return type.name() + "(0)";
125 case Type::kMatrix_Kind: return type.name() + "(1)";
126 default: ABORT("unsupported default_value type\n");
127 }
128 }
129
default_value(const Variable & var)130 static String default_value(const Variable& var) {
131 if (var.fModifiers.fLayout.fCType == "GrColor4f") {
132 return "GrColor4f::kIllegalConstructor";
133 }
134 return default_value(var.fType);
135 }
136
is_private(const Variable & var)137 static bool is_private(const Variable& var) {
138 return !(var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
139 !(var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
140 var.fStorage == Variable::kGlobal_Storage &&
141 var.fModifiers.fLayout.fBuiltin == -1;
142 }
143
writeRuntimeValue(const Type & type,const Layout & layout,const String & cppCode)144 void CPPCodeGenerator::writeRuntimeValue(const Type& type, const Layout& layout,
145 const String& cppCode) {
146 if (type.isFloat()) {
147 this->write("%f");
148 fFormatArgs.push_back(cppCode);
149 } else if (type == *fContext.fInt_Type) {
150 this->write("%d");
151 fFormatArgs.push_back(cppCode);
152 } else if (type == *fContext.fBool_Type) {
153 this->write("%s");
154 fFormatArgs.push_back("(" + cppCode + " ? \"true\" : \"false\")");
155 } else if (type == *fContext.fFloat2_Type || type == *fContext.fHalf2_Type) {
156 this->write(type.name() + "(%f, %f)");
157 fFormatArgs.push_back(cppCode + ".fX");
158 fFormatArgs.push_back(cppCode + ".fY");
159 } else if (type == *fContext.fFloat4_Type || type == *fContext.fHalf4_Type) {
160 this->write(type.name() + "(%f, %f, %f, %f)");
161 if (layout.fCType == "SkPMColor") {
162 fFormatArgs.push_back("SkGetPackedR32(" + cppCode + ") / 255.0");
163 fFormatArgs.push_back("SkGetPackedG32(" + cppCode + ") / 255.0");
164 fFormatArgs.push_back("SkGetPackedB32(" + cppCode + ") / 255.0");
165 fFormatArgs.push_back("SkGetPackedA32(" + cppCode + ") / 255.0");
166 } else if (layout.fCType == "GrColor4f") {
167 fFormatArgs.push_back(cppCode + ".fRGBA[0]");
168 fFormatArgs.push_back(cppCode + ".fRGBA[1]");
169 fFormatArgs.push_back(cppCode + ".fRGBA[2]");
170 fFormatArgs.push_back(cppCode + ".fRGBA[3]");
171 } else {
172 fFormatArgs.push_back(cppCode + ".left()");
173 fFormatArgs.push_back(cppCode + ".top()");
174 fFormatArgs.push_back(cppCode + ".right()");
175 fFormatArgs.push_back(cppCode + ".bottom()");
176 }
177 } else if (type.kind() == Type::kEnum_Kind) {
178 this->write("%d");
179 fFormatArgs.push_back("(int) " + cppCode);
180 } else if (type == *fContext.fInt4_Type || type == *fContext.fShort4_Type) {
181 this->write(type.name() + "(%d, %d, %d, %d)");
182 fFormatArgs.push_back(cppCode + ".left()");
183 fFormatArgs.push_back(cppCode + ".top()");
184 fFormatArgs.push_back(cppCode + ".right()");
185 fFormatArgs.push_back(cppCode + ".bottom()");
186 } else {
187 printf("unsupported runtime value type '%s'\n", String(type.fName).c_str());
188 ASSERT(false);
189 }
190 }
191
writeVarInitializer(const Variable & var,const Expression & value)192 void CPPCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
193 if (is_private(var)) {
194 this->writeRuntimeValue(var.fType, var.fModifiers.fLayout, var.fName);
195 } else {
196 this->writeExpression(value, kTopLevel_Precedence);
197 }
198 }
199
getSamplerHandle(const Variable & var)200 String CPPCodeGenerator::getSamplerHandle(const Variable& var) {
201 int samplerCount = 0;
202 for (const auto param : fSectionAndParameterHelper.getParameters()) {
203 if (&var == param) {
204 return "args.fTexSamplers[" + to_string(samplerCount) + "]";
205 }
206 if (param->fType.kind() == Type::kSampler_Kind) {
207 ++samplerCount;
208 }
209 }
210 ABORT("should have found sampler in parameters\n");
211 }
212
writeIntLiteral(const IntLiteral & i)213 void CPPCodeGenerator::writeIntLiteral(const IntLiteral& i) {
214 this->write(to_string((int32_t) i.fValue));
215 }
216
writeSwizzle(const Swizzle & swizzle)217 void CPPCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
218 if (fCPPMode) {
219 ASSERT(swizzle.fComponents.size() == 1); // no support for multiple swizzle components yet
220 this->writeExpression(*swizzle.fBase, kPostfix_Precedence);
221 switch (swizzle.fComponents[0]) {
222 case 0: this->write(".left()"); break;
223 case 1: this->write(".top()"); break;
224 case 2: this->write(".right()"); break;
225 case 3: this->write(".bottom()"); break;
226 }
227 } else {
228 INHERITED::writeSwizzle(swizzle);
229 }
230 }
231
writeVariableReference(const VariableReference & ref)232 void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
233 if (fCPPMode) {
234 this->write(ref.fVariable.fName);
235 return;
236 }
237 switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
238 case SK_INCOLOR_BUILTIN:
239 this->write("%s");
240 fFormatArgs.push_back(String("args.fInputColor ? args.fInputColor : \"half4(1)\""));
241 break;
242 case SK_OUTCOLOR_BUILTIN:
243 this->write("%s");
244 fFormatArgs.push_back(String("args.fOutputColor"));
245 break;
246 default:
247 if (ref.fVariable.fType.kind() == Type::kSampler_Kind) {
248 this->write("%s");
249 fFormatArgs.push_back("fragBuilder->getProgramBuilder()->samplerVariable(" +
250 this->getSamplerHandle(ref.fVariable) + ").c_str()");
251 return;
252 }
253 if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) {
254 this->write("%s");
255 String name = ref.fVariable.fName;
256 String var = String::printf("args.fUniformHandler->getUniformCStr(%sVar)",
257 HCodeGenerator::FieldName(name.c_str()).c_str());
258 String code;
259 if (ref.fVariable.fModifiers.fLayout.fWhen.size()) {
260 code = String::printf("%sVar.isValid() ? %s : \"%s\"",
261 HCodeGenerator::FieldName(name.c_str()).c_str(),
262 var.c_str(),
263 default_value(ref.fVariable.fType).c_str());
264 } else {
265 code = var;
266 }
267 fFormatArgs.push_back(code);
268 } else if (SectionAndParameterHelper::IsParameter(ref.fVariable)) {
269 String name(ref.fVariable.fName);
270 this->writeRuntimeValue(ref.fVariable.fType, ref.fVariable.fModifiers.fLayout,
271 String::printf("_outer.%s()", name.c_str()).c_str());
272 } else {
273 this->write(ref.fVariable.fName);
274 }
275 }
276 }
277
writeIfStatement(const IfStatement & s)278 void CPPCodeGenerator::writeIfStatement(const IfStatement& s) {
279 if (s.fIsStatic) {
280 this->write("@");
281 }
282 INHERITED::writeIfStatement(s);
283 }
284
writeSwitchStatement(const SwitchStatement & s)285 void CPPCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
286 if (s.fIsStatic) {
287 this->write("@");
288 }
289 INHERITED::writeSwitchStatement(s);
290 }
291
writeFunctionCall(const FunctionCall & c)292 void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
293 if (c.fFunction.fBuiltin && c.fFunction.fName == "process") {
294 ASSERT(c.fArguments.size() == 1);
295 ASSERT(Expression::kVariableReference_Kind == c.fArguments[0]->fKind);
296 int index = 0;
297 bool found = false;
298 for (const auto& p : fProgram.fElements) {
299 if (ProgramElement::kVar_Kind == p->fKind) {
300 const VarDeclarations* decls = (const VarDeclarations*) p.get();
301 for (const auto& raw : decls->fVars) {
302 VarDeclaration& decl = (VarDeclaration&) *raw;
303 if (decl.fVar == &((VariableReference&) *c.fArguments[0]).fVariable) {
304 found = true;
305 } else if (decl.fVar->fType == *fContext.fFragmentProcessor_Type) {
306 ++index;
307 }
308 }
309 }
310 if (found) {
311 break;
312 }
313 }
314 ASSERT(found);
315 String childName = "_child" + to_string(index);
316 fExtraEmitCodeCode += " SkString " + childName + "(\"" + childName + "\");\n" +
317 " this->emitChild(" + to_string(index) + ", &" + childName +
318 ", args);\n";
319 this->write("%s");
320 fFormatArgs.push_back(childName + ".c_str()");
321 return;
322 }
323 INHERITED::writeFunctionCall(c);
324 if (c.fFunction.fBuiltin && c.fFunction.fName == "texture") {
325 this->write(".%s");
326 ASSERT(c.fArguments.size() >= 1);
327 ASSERT(c.fArguments[0]->fKind == Expression::kVariableReference_Kind);
328 String sampler = this->getSamplerHandle(((VariableReference&) *c.fArguments[0]).fVariable);
329 fFormatArgs.push_back("fragBuilder->getProgramBuilder()->samplerSwizzle(" + sampler +
330 ").c_str()");
331 }
332 }
333
writeFunction(const FunctionDefinition & f)334 void CPPCodeGenerator::writeFunction(const FunctionDefinition& f) {
335 if (f.fDeclaration.fName == "main") {
336 fFunctionHeader = "";
337 OutputStream* oldOut = fOut;
338 StringStream buffer;
339 fOut = &buffer;
340 for (const auto& s : ((Block&) *f.fBody).fStatements) {
341 this->writeStatement(*s);
342 this->writeLine();
343 }
344
345 fOut = oldOut;
346 this->write(fFunctionHeader);
347 this->write(buffer.str());
348 } else {
349 INHERITED::writeFunction(f);
350 }
351 }
352
writeSetting(const Setting & s)353 void CPPCodeGenerator::writeSetting(const Setting& s) {
354 static constexpr const char* kPrefix = "sk_Args.";
355 if (!strncmp(s.fName.c_str(), kPrefix, strlen(kPrefix))) {
356 const char* name = s.fName.c_str() + strlen(kPrefix);
357 this->writeRuntimeValue(s.fType, Layout(), HCodeGenerator::FieldName(name).c_str());
358 } else {
359 this->write(s.fName.c_str());
360 }
361 }
362
writeSection(const char * name,const char * prefix)363 bool CPPCodeGenerator::writeSection(const char* name, const char* prefix) {
364 const Section* s = fSectionAndParameterHelper.getSection(name);
365 if (s) {
366 this->writef("%s%s", prefix, s->fText.c_str());
367 return true;
368 }
369 return false;
370 }
371
writeProgramElement(const ProgramElement & p)372 void CPPCodeGenerator::writeProgramElement(const ProgramElement& p) {
373 if (p.fKind == ProgramElement::kSection_Kind) {
374 return;
375 }
376 if (p.fKind == ProgramElement::kVar_Kind) {
377 const VarDeclarations& decls = (const VarDeclarations&) p;
378 if (!decls.fVars.size()) {
379 return;
380 }
381 const Variable& var = *((VarDeclaration&) *decls.fVars[0]).fVar;
382 if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) ||
383 -1 != var.fModifiers.fLayout.fBuiltin) {
384 return;
385 }
386 }
387 INHERITED::writeProgramElement(p);
388 }
389
addUniform(const Variable & var)390 void CPPCodeGenerator::addUniform(const Variable& var) {
391 if (!needs_uniform_var(var)) {
392 return;
393 }
394 const char* precision;
395 if (var.fModifiers.fFlags & Modifiers::kHighp_Flag) {
396 precision = "kHigh_GrSLPrecision";
397 } else if (var.fModifiers.fFlags & Modifiers::kMediump_Flag) {
398 precision = "kMedium_GrSLPrecision";
399 } else if (var.fModifiers.fFlags & Modifiers::kLowp_Flag) {
400 precision = "kLow_GrSLPrecision";
401 } else {
402 precision = "kDefault_GrSLPrecision";
403 }
404 const char* type;
405 if (var.fType == *fContext.fFloat_Type) {
406 type = "kFloat_GrSLType";
407 } else if (var.fType == *fContext.fHalf_Type) {
408 type = "kHalf_GrSLType";
409 } else if (var.fType == *fContext.fFloat2_Type) {
410 type = "kFloat2_GrSLType";
411 } else if (var.fType == *fContext.fHalf2_Type) {
412 type = "kHalf2_GrSLType";
413 } else if (var.fType == *fContext.fFloat4_Type) {
414 type = "kFloat4_GrSLType";
415 } else if (var.fType == *fContext.fHalf4_Type) {
416 type = "kHalf4_GrSLType";
417 } else if (var.fType == *fContext.fFloat4x4_Type) {
418 type = "kFloat4x4_GrSLType";
419 } else if (var.fType == *fContext.fHalf4x4_Type) {
420 type = "kHalf4x4_GrSLType";
421 } else {
422 ABORT("unsupported uniform type: %s %s;\n", String(var.fType.fName).c_str(),
423 String(var.fName).c_str());
424 }
425 if (var.fModifiers.fLayout.fWhen.size()) {
426 this->writef(" if (%s) {\n ", var.fModifiers.fLayout.fWhen.c_str());
427 }
428 String name(var.fName);
429 this->writef(" %sVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, %s, "
430 "%s, \"%s\");\n", HCodeGenerator::FieldName(name.c_str()).c_str(), type, precision,
431 name.c_str());
432 if (var.fModifiers.fLayout.fWhen.size()) {
433 this->write(" }\n");
434 }
435 }
436
writePrivateVars()437 void CPPCodeGenerator::writePrivateVars() {
438 for (const auto& p : fProgram.fElements) {
439 if (ProgramElement::kVar_Kind == p->fKind) {
440 const VarDeclarations* decls = (const VarDeclarations*) p.get();
441 for (const auto& raw : decls->fVars) {
442 VarDeclaration& decl = (VarDeclaration&) *raw;
443 if (is_private(*decl.fVar)) {
444 if (decl.fVar->fType == *fContext.fFragmentProcessor_Type) {
445 fErrors.error(decl.fOffset,
446 "fragmentProcessor variables must be declared 'in'");
447 return;
448 }
449 this->writef("%s %s = %s;\n",
450 HCodeGenerator::FieldType(fContext, decl.fVar->fType,
451 decl.fVar->fModifiers.fLayout).c_str(),
452 String(decl.fVar->fName).c_str(),
453 default_value(*decl.fVar).c_str());
454 }
455 }
456 }
457 }
458 }
459
writePrivateVarValues()460 void CPPCodeGenerator::writePrivateVarValues() {
461 for (const auto& p : fProgram.fElements) {
462 if (ProgramElement::kVar_Kind == p->fKind) {
463 const VarDeclarations* decls = (const VarDeclarations*) p.get();
464 for (const auto& raw : decls->fVars) {
465 VarDeclaration& decl = (VarDeclaration&) *raw;
466 if (is_private(*decl.fVar) && decl.fValue) {
467 this->writef("%s = ", String(decl.fVar->fName).c_str());
468 fCPPMode = true;
469 this->writeExpression(*decl.fValue, kAssignment_Precedence);
470 fCPPMode = false;
471 this->write(";\n");
472 }
473 }
474 }
475 }
476 }
477
is_accessible(const Variable & var)478 static bool is_accessible(const Variable& var) {
479 return Type::kSampler_Kind != var.fType.kind() &&
480 Type::kOther_Kind != var.fType.kind();
481 }
482
writeCodeAppend(const String & code)483 void CPPCodeGenerator::writeCodeAppend(const String& code) {
484 // codeAppendf can only handle appending 1024 bytes at a time, so we need to break the string
485 // into chunks. Unfortunately we can't tell exactly how long the string is going to end up,
486 // because printf escape sequences get replaced by strings of unknown length, but keeping the
487 // format string below 512 bytes is probably safe.
488 static constexpr size_t maxChunkSize = 512;
489 size_t start = 0;
490 size_t index = 0;
491 size_t argStart = 0;
492 size_t argCount;
493 while (index < code.size()) {
494 argCount = 0;
495 this->write(" fragBuilder->codeAppendf(\"");
496 while (index < code.size() && index < start + maxChunkSize) {
497 if ('%' == code[index]) {
498 if (index == start + maxChunkSize - 1 || index == code.size() - 1) {
499 break;
500 }
501 if (code[index + 1] != '%') {
502 ++argCount;
503 }
504 } else if ('\\' == code[index] && index == start + maxChunkSize - 1) {
505 // avoid splitting an escape sequence that happens to fall across a chunk boundary
506 break;
507 }
508 ++index;
509 }
510 fOut->write(code.c_str() + start, index - start);
511 this->write("\"");
512 for (size_t i = argStart; i < argStart + argCount; ++i) {
513 this->writef(", %s", fFormatArgs[i].c_str());
514 }
515 this->write(");\n");
516 argStart += argCount;
517 start = index;
518 }
519 }
520
writeEmitCode(std::vector<const Variable * > & uniforms)521 bool CPPCodeGenerator::writeEmitCode(std::vector<const Variable*>& uniforms) {
522 this->write(" void emitCode(EmitArgs& args) override {\n"
523 " GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n");
524 this->writef(" const %s& _outer = args.fFp.cast<%s>();\n"
525 " (void) _outer;\n",
526 fFullName.c_str(), fFullName.c_str());
527 for (const auto& p : fProgram.fElements) {
528 if (ProgramElement::kVar_Kind == p->fKind) {
529 const VarDeclarations* decls = (const VarDeclarations*) p.get();
530 for (const auto& raw : decls->fVars) {
531 VarDeclaration& decl = (VarDeclaration&) *raw;
532 String nameString(decl.fVar->fName);
533 const char* name = nameString.c_str();
534 if (SectionAndParameterHelper::IsParameter(*decl.fVar) &&
535 is_accessible(*decl.fVar)) {
536 this->writef(" auto %s = _outer.%s();\n"
537 " (void) %s;\n",
538 name, name, name);
539 }
540 }
541 }
542 }
543 this->writePrivateVarValues();
544 for (const auto u : uniforms) {
545 this->addUniform(*u);
546 }
547 this->writeSection(EMIT_CODE_SECTION);
548 OutputStream* old = fOut;
549 StringStream mainBuffer;
550 fOut = &mainBuffer;
551 bool result = INHERITED::generateCode();
552 fOut = old;
553 this->writef("%s", fExtraEmitCodeCode.c_str());
554 this->writeCodeAppend(mainBuffer.str());
555 this->write(" }\n");
556 return result;
557 }
558
writeSetData(std::vector<const Variable * > & uniforms)559 void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
560 const char* fullName = fFullName.c_str();
561 const Section* section = fSectionAndParameterHelper.getSection(SET_DATA_SECTION);
562 const char* pdman = section ? section->fArgument.c_str() : "pdman";
563 this->writef(" void onSetData(const GrGLSLProgramDataManager& %s, "
564 "const GrFragmentProcessor& _proc) override {\n",
565 pdman);
566 bool wroteProcessor = false;
567 for (const auto u : uniforms) {
568 if (u->fModifiers.fFlags & Modifiers::kIn_Flag) {
569 if (!wroteProcessor) {
570 this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName, fullName);
571 wroteProcessor = true;
572 this->writef(" {\n");
573 }
574 String nameString(u->fName);
575 const char* name = nameString.c_str();
576 if (u->fType == *fContext.fFloat4_Type || u->fType == *fContext.fHalf4_Type) {
577 this->writef(" const SkRect %sValue = _outer.%s();\n"
578 " %s.set4fv(%sVar, 1, (float*) &%sValue);\n",
579 name, name, pdman, HCodeGenerator::FieldName(name).c_str(), name);
580 } else if (u->fType == *fContext.fFloat4x4_Type ||
581 u->fType == *fContext.fHalf4x4_Type) {
582 this->writef(" float %sValue[16];\n"
583 " _outer.%s().asColMajorf(%sValue);\n"
584 " %s.setMatrix4f(%sVar, %sValue);\n",
585 name, name, name, pdman, HCodeGenerator::FieldName(name).c_str(),
586 name);
587 } else if (u->fType == *fContext.fFragmentProcessor_Type) {
588 // do nothing
589 } else {
590 this->writef(" %s.set1f(%sVar, _outer.%s());\n",
591 pdman, HCodeGenerator::FieldName(name).c_str(), name);
592 }
593 }
594 }
595 if (wroteProcessor) {
596 this->writef(" }\n");
597 }
598 if (section) {
599 int samplerIndex = 0;
600 for (const auto& p : fProgram.fElements) {
601 if (ProgramElement::kVar_Kind == p->fKind) {
602 const VarDeclarations* decls = (const VarDeclarations*) p.get();
603 for (const auto& raw : decls->fVars) {
604 VarDeclaration& decl = (VarDeclaration&) *raw;
605 String nameString(decl.fVar->fName);
606 const char* name = nameString.c_str();
607 if (decl.fVar->fType.kind() == Type::kSampler_Kind) {
608 this->writef(" GrSurfaceProxy& %sProxy = "
609 "*_outer.textureSampler(%d).proxy();\n",
610 name, samplerIndex);
611 this->writef(" GrTexture& %s = *%sProxy.priv().peekTexture();\n",
612 name, name);
613 this->writef(" (void) %s;\n", name);
614 ++samplerIndex;
615 } else if (needs_uniform_var(*decl.fVar)) {
616 this->writef(" UniformHandle& %s = %sVar;\n"
617 " (void) %s;\n",
618 name, HCodeGenerator::FieldName(name).c_str(), name);
619 } else if (SectionAndParameterHelper::IsParameter(*decl.fVar) &&
620 decl.fVar->fType != *fContext.fFragmentProcessor_Type) {
621 if (!wroteProcessor) {
622 this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName,
623 fullName);
624 wroteProcessor = true;
625 }
626 this->writef(" auto %s = _outer.%s();\n"
627 " (void) %s;\n",
628 name, name, name);
629 }
630 }
631 }
632 }
633 this->writeSection(SET_DATA_SECTION);
634 }
635 this->write(" }\n");
636 }
637
writeClone()638 void CPPCodeGenerator::writeClone() {
639 if (!this->writeSection(CLONE_SECTION)) {
640 if (fSectionAndParameterHelper.getSection(FIELDS_SECTION)) {
641 fErrors.error(0, "fragment processors with custom @fields must also have a custom"
642 "@clone");
643 }
644 this->writef("%s::%s(const %s& src)\n"
645 ": INHERITED(k%s_ClassID, src.optimizationFlags())", fFullName.c_str(),
646 fFullName.c_str(), fFullName.c_str(), fFullName.c_str());
647 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
648 if (param->fType == *fContext.fFragmentProcessor_Type) {
649 continue;
650 }
651 String fieldName = HCodeGenerator::FieldName(String(param->fName).c_str());
652 this->writef("\n, %s(src.%s)",
653 fieldName.c_str(),
654 fieldName.c_str());
655 }
656 for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) {
657 String fieldName = HCodeGenerator::FieldName(s->fArgument.c_str());
658 this->writef("\n, %sCoordTransform(src.%sCoordTransform)", fieldName.c_str(),
659 fieldName.c_str());
660 }
661 this->writef(" {\n");
662 int childCount = 0;
663 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
664 if (param->fType.kind() == Type::kSampler_Kind) {
665 this->writef(" this->addTextureSampler(&%s);\n",
666 HCodeGenerator::FieldName(String(param->fName).c_str()).c_str());
667 } else if (param->fType == *fContext.fFragmentProcessor_Type) {
668 this->writef(" this->registerChildProcessor(src.childProcessor(%d).clone());"
669 "\n", childCount++);
670 }
671 }
672 for (const Section* s : fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION)) {
673 String field = HCodeGenerator::FieldName(s->fArgument.c_str());
674 this->writef(" this->addCoordTransform(&%sCoordTransform);\n", field.c_str());
675 }
676 this->write("}\n");
677 this->writef("std::unique_ptr<GrFragmentProcessor> %s::clone() const {\n",
678 fFullName.c_str());
679 this->writef(" return std::unique_ptr<GrFragmentProcessor>(new %s(*this));\n",
680 fFullName.c_str());
681 this->write("}\n");
682 }
683 }
684
writeTest()685 void CPPCodeGenerator::writeTest() {
686 const Section* test = fSectionAndParameterHelper.getSection(TEST_CODE_SECTION);
687 if (test) {
688 this->writef(
689 "GR_DEFINE_FRAGMENT_PROCESSOR_TEST(%s);\n"
690 "#if GR_TEST_UTILS\n"
691 "std::unique_ptr<GrFragmentProcessor> %s::TestCreate(GrProcessorTestData* %s) {\n",
692 fFullName.c_str(),
693 fFullName.c_str(),
694 test->fArgument.c_str());
695 this->writeSection(TEST_CODE_SECTION);
696 this->write("}\n"
697 "#endif\n");
698 }
699 }
700
writeGetKey()701 void CPPCodeGenerator::writeGetKey() {
702 this->writef("void %s::onGetGLSLProcessorKey(const GrShaderCaps& caps, "
703 "GrProcessorKeyBuilder* b) const {\n",
704 fFullName.c_str());
705 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
706 String nameString(param->fName);
707 const char* name = nameString.c_str();
708 if (param->fModifiers.fLayout.fKey != Layout::kNo_Key &&
709 (param->fModifiers.fFlags & Modifiers::kUniform_Flag)) {
710 fErrors.error(param->fOffset,
711 "layout(key) may not be specified on uniforms");
712 }
713 switch (param->fModifiers.fLayout.fKey) {
714 case Layout::kKey_Key:
715 if (param->fType == *fContext.fFloat4x4_Type) {
716 ABORT("no automatic key handling for float4x4\n");
717 } else if (param->fType == *fContext.fFloat2_Type) {
718 this->writef(" b->add32(%s.fX);\n",
719 HCodeGenerator::FieldName(name).c_str());
720 this->writef(" b->add32(%s.fY);\n",
721 HCodeGenerator::FieldName(name).c_str());
722 } else if (param->fType == *fContext.fFloat4_Type) {
723 this->writef(" b->add32(%s.x());\n",
724 HCodeGenerator::FieldName(name).c_str());
725 this->writef(" b->add32(%s.y());\n",
726 HCodeGenerator::FieldName(name).c_str());
727 this->writef(" b->add32(%s.width());\n",
728 HCodeGenerator::FieldName(name).c_str());
729 this->writef(" b->add32(%s.height());\n",
730 HCodeGenerator::FieldName(name).c_str());
731 } else {
732 this->writef(" b->add32((int32_t) %s);\n",
733 HCodeGenerator::FieldName(name).c_str());
734 }
735 break;
736 case Layout::kIdentity_Key:
737 if (param->fType.kind() != Type::kMatrix_Kind) {
738 fErrors.error(param->fOffset,
739 "layout(key=identity) requires matrix type");
740 }
741 this->writef(" b->add32(%s.isIdentity() ? 1 : 0);\n",
742 HCodeGenerator::FieldName(name).c_str());
743 break;
744 case Layout::kNo_Key:
745 break;
746 }
747 }
748 this->write("}\n");
749 }
750
generateCode()751 bool CPPCodeGenerator::generateCode() {
752 std::vector<const Variable*> uniforms;
753 for (const auto& p : fProgram.fElements) {
754 if (ProgramElement::kVar_Kind == p->fKind) {
755 const VarDeclarations* decls = (const VarDeclarations*) p.get();
756 for (const auto& raw : decls->fVars) {
757 VarDeclaration& decl = (VarDeclaration&) *raw;
758 if ((decl.fVar->fModifiers.fFlags & Modifiers::kUniform_Flag) &&
759 decl.fVar->fType.kind() != Type::kSampler_Kind) {
760 uniforms.push_back(decl.fVar);
761 }
762 }
763 }
764 }
765 const char* baseName = fName.c_str();
766 const char* fullName = fFullName.c_str();
767 this->writef("%s\n", HCodeGenerator::GetHeader(fProgram, fErrors).c_str());
768 this->writef(kFragmentProcessorHeader, fullName);
769 this->writef("#include \"%s.h\"\n"
770 "#if SK_SUPPORT_GPU\n", fullName);
771 this->writeSection(CPP_SECTION);
772 this->writef("#include \"glsl/GrGLSLFragmentProcessor.h\"\n"
773 "#include \"glsl/GrGLSLFragmentShaderBuilder.h\"\n"
774 "#include \"glsl/GrGLSLProgramBuilder.h\"\n"
775 "#include \"GrTexture.h\"\n"
776 "#include \"SkSLCPP.h\"\n"
777 "#include \"SkSLUtil.h\"\n"
778 "class GrGLSL%s : public GrGLSLFragmentProcessor {\n"
779 "public:\n"
780 " GrGLSL%s() {}\n",
781 baseName, baseName);
782 bool result = this->writeEmitCode(uniforms);
783 this->write("private:\n");
784 this->writeSetData(uniforms);
785 this->writePrivateVars();
786 for (const auto& u : uniforms) {
787 if (needs_uniform_var(*u) && !(u->fModifiers.fFlags & Modifiers::kIn_Flag)) {
788 this->writef(" UniformHandle %sVar;\n",
789 HCodeGenerator::FieldName(String(u->fName).c_str()).c_str());
790 }
791 }
792 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
793 if (needs_uniform_var(*param)) {
794 this->writef(" UniformHandle %sVar;\n",
795 HCodeGenerator::FieldName(String(param->fName).c_str()).c_str());
796 }
797 }
798 this->writef("};\n"
799 "GrGLSLFragmentProcessor* %s::onCreateGLSLInstance() const {\n"
800 " return new GrGLSL%s();\n"
801 "}\n",
802 fullName, baseName);
803 this->writeGetKey();
804 this->writef("bool %s::onIsEqual(const GrFragmentProcessor& other) const {\n"
805 " const %s& that = other.cast<%s>();\n"
806 " (void) that;\n",
807 fullName, fullName, fullName);
808 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
809 if (param->fType == *fContext.fFragmentProcessor_Type) {
810 continue;
811 }
812 String nameString(param->fName);
813 const char* name = nameString.c_str();
814 this->writef(" if (%s != that.%s) return false;\n",
815 HCodeGenerator::FieldName(name).c_str(),
816 HCodeGenerator::FieldName(name).c_str());
817 }
818 this->write(" return true;\n"
819 "}\n");
820 this->writeClone();
821 this->writeTest();
822 this->writeSection(CPP_END_SECTION);
823 this->write("#endif\n");
824 result &= 0 == fErrors.errorCount();
825 return result;
826 }
827
828 } // namespace
829