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 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 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 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 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 51 void CPPCodeGenerator::writeHeader() { 52 } 53 54 void CPPCodeGenerator::writePrecisionModifier() { 55 } 56 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 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 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 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 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 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 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 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 228 void CPPCodeGenerator::writeIfStatement(const IfStatement& s) { 229 if (s.fIsStatic) { 230 this->write("@"); 231 } 232 INHERITED::writeIfStatement(s); 233 } 234 235 void CPPCodeGenerator::writeSwitchStatement(const SwitchStatement& s) { 236 if (s.fIsStatic) { 237 this->write("@"); 238 } 239 INHERITED::writeSwitchStatement(s); 240 } 241 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 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 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 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 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 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 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 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 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 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 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 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 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