aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sksl/SkSLCPPCodeGenerator.cpp
diff options
context:
space:
mode:
authorGravatar Ethan Nicholas <ethannicholas@google.com>2017-06-27 11:20:22 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-06-27 18:27:57 +0000
commitc070939fd1a954b7a492bc30f0cf64a664b90181 (patch)
tree6b1167726bc9ac4d2073f893c699b40c70f63ba1 /src/sksl/SkSLCPPCodeGenerator.cpp
parent26249e0e1d1b18a1e67195a2998b49958426f8ba (diff)
Re-land sksl fragment processor support
This reverts commit ed50200682e0de72c3abecaa4d5324ebcd1ed9f9. Bug: skia: Change-Id: I9caa7454b391450620d6989dc472abb3cf7a2cab Reviewed-on: https://skia-review.googlesource.com/20965 Reviewed-by: Ben Wagner <benjaminwagner@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Diffstat (limited to 'src/sksl/SkSLCPPCodeGenerator.cpp')
-rw-r--r--src/sksl/SkSLCPPCodeGenerator.cpp600
1 files changed, 600 insertions, 0 deletions
diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp
new file mode 100644
index 0000000000..0b3c7d58da
--- /dev/null
+++ b/src/sksl/SkSLCPPCodeGenerator.cpp
@@ -0,0 +1,600 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkSLCPPCodeGenerator.h"
+
+#include "SkSLCompiler.h"
+#include "SkSLHCodeGenerator.h"
+
+namespace SkSL {
+
+static bool needs_uniform_var(const Variable& var) {
+ return (var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
+ strcmp(var.fType.fName.c_str(), "colorSpaceXform");
+}
+
+CPPCodeGenerator::CPPCodeGenerator(const Context* context, const Program* program,
+ ErrorReporter* errors, String name, OutputStream* out)
+: INHERITED(context, program, errors, out)
+, fName(std::move(name))
+, fFullName(String::printf("Gr%s", fName.c_str()))
+, fSectionAndParameterHelper(*program, *errors) {
+ fLineEnding = "\\n";
+}
+
+void CPPCodeGenerator::writef(const char* s, va_list va) {
+ static constexpr int BUFFER_SIZE = 1024;
+ char buffer[BUFFER_SIZE];
+ int length = vsnprintf(buffer, BUFFER_SIZE, s, va);
+ if (length < BUFFER_SIZE) {
+ fOut->write(buffer, length);
+ } else {
+ std::unique_ptr<char[]> heap(new char[length + 1]);
+ vsprintf(heap.get(), s, va);
+ fOut->write(heap.get(), length);
+ }
+}
+
+void CPPCodeGenerator::writef(const char* s, ...) {
+ va_list va;
+ va_start(va, s);
+ this->writef(s, va);
+ va_end(va);
+}
+
+void CPPCodeGenerator::writeHeader() {
+}
+
+void CPPCodeGenerator::writePrecisionModifier() {
+}
+
+void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
+ Precedence parentPrecedence) {
+ if (b.fOperator == Token::PERCENT) {
+ // need to use "%%" instead of "%" b/c the code will be inside of a printf
+ Precedence precedence = GetBinaryPrecedence(b.fOperator);
+ if (precedence >= parentPrecedence) {
+ this->write("(");
+ }
+ this->writeExpression(*b.fLeft, precedence);
+ this->write(" %% ");
+ this->writeExpression(*b.fRight, precedence);
+ if (precedence >= parentPrecedence) {
+ this->write(")");
+ }
+ } else {
+ INHERITED::writeBinaryExpression(b, parentPrecedence);
+ }
+}
+
+void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) {
+ const Expression& base = *i.fBase;
+ if (base.fKind == Expression::kVariableReference_Kind) {
+ int builtin = ((VariableReference&) base).fVariable.fModifiers.fLayout.fBuiltin;
+ if (SK_TRANSFORMEDCOORDS2D_BUILTIN == builtin) {
+ this->write("%s");
+ if (i.fIndex->fKind != Expression::kIntLiteral_Kind) {
+ fErrors.error(i.fIndex->fPosition,
+ "index into sk_TransformedCoords2D must be an integer literal");
+ return;
+ }
+ int64_t index = ((IntLiteral&) *i.fIndex).fValue;
+ String name = "sk_TransformedCoords2D_" + to_string(index);
+ fFormatArgs.push_back(name + ".c_str()");
+ if (fWrittenTransformedCoords.find(index) == fWrittenTransformedCoords.end()) {
+ fExtraEmitCodeCode += " SkSL::String " + name +
+ " = fragBuilder->ensureCoords2D(args.fTransformedCoords[" +
+ to_string(index) + "]);\n";
+ fWrittenTransformedCoords.insert(index);
+ }
+ return;
+ } else if (SK_TEXTURESAMPLERS_BUILTIN == builtin) {
+ this->write("%s");
+ if (i.fIndex->fKind != Expression::kIntLiteral_Kind) {
+ fErrors.error(i.fIndex->fPosition,
+ "index into sk_TextureSamplers must be an integer literal");
+ return;
+ }
+ int64_t index = ((IntLiteral&) *i.fIndex).fValue;
+ fFormatArgs.push_back(" fragBuilder->getProgramBuilder()->samplerVariable("
+ "args.fTexSamplers[" + to_string(index) + "]).c_str()");
+ return;
+ }
+ }
+ INHERITED::writeIndexExpression(i);
+}
+
+static const char* default_value(const Type& type) {
+ const char* name = type.name().c_str();
+ if (!strcmp(name, "float")) {
+ return "0.0";
+ } else if (!strcmp(name, "vec2")) {
+ return "vec2(0.0)";
+ } else if (!strcmp(name, "vec3")) {
+ return "vec3(0.0)";
+ } else if (!strcmp(name, "vec4")) {
+ return "vec4(0.0)";
+ } else if (!strcmp(name, "mat4") || !strcmp(name, "colorSpaceXform")) {
+ return "mat4(1.0)";
+ }
+ ABORT("unsupported default_value type\n");
+}
+
+static bool is_private(const Variable& var) {
+ return !(var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
+ !(var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
+ var.fStorage == Variable::kGlobal_Storage &&
+ var.fModifiers.fLayout.fBuiltin == -1;
+}
+
+void CPPCodeGenerator::writeRuntimeValue(const Type& type, const String& cppCode) {
+ if (type == *fContext.fFloat_Type) {
+ this->write("%f");
+ fFormatArgs.push_back(cppCode);
+ } else if (type == *fContext.fInt_Type) {
+ this->write("%d");
+ fFormatArgs.push_back(cppCode);
+ } else if (type == *fContext.fBool_Type) {
+ this->write("%s");
+ fFormatArgs.push_back("(" + cppCode + " ? \"true\" : \"false\")");
+ } else if (type == *fContext.fVec2_Type) {
+ this->write("vec2(%f, %f)");
+ fFormatArgs.push_back(cppCode + ".fX");
+ fFormatArgs.push_back(cppCode + ".fY");
+ } else {
+ printf("%s\n", type.name().c_str());
+ ABORT("unsupported runtime value type\n");
+ }
+}
+
+void CPPCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
+ if (is_private(var)) {
+ this->writeRuntimeValue(var.fType, var.fName);
+ } else {
+ this->writeExpression(value, kTopLevel_Precedence);
+ }
+}
+
+void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
+ switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
+ case SK_INCOLOR_BUILTIN:
+ this->write("%s");
+ fFormatArgs.push_back(String("args.fInputColor ? args.fInputColor : \"vec4(1)\""));
+ break;
+ case SK_OUTCOLOR_BUILTIN:
+ this->write("%s");
+ fFormatArgs.push_back(String("args.fOutputColor"));
+ break;
+ default:
+ if (ref.fVariable.fType.kind() == Type::kSampler_Kind) {
+ int samplerCount = 0;
+ for (const auto param : fSectionAndParameterHelper.fParameters) {
+ if (&ref.fVariable == param) {
+ this->write("%s");
+ fFormatArgs.push_back("fragBuilder->getProgramBuilder()->samplerVariable("
+ "args.fTexSamplers[" + to_string(samplerCount) +
+ "]).c_str()");
+ return;
+ }
+ if (param->fType.kind() == Type::kSampler_Kind) {
+ ++samplerCount;
+ }
+ }
+ ABORT("should have found sampler in parameters\n");
+ }
+ if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) {
+ this->write("%s");
+ String name = ref.fVariable.fName;
+ String var;
+ if (ref.fVariable.fType == *fContext.fColorSpaceXform_Type) {
+ ASSERT(fNeedColorSpaceHelper);
+ var = String::printf("fColorSpaceHelper.isValid() ? "
+ "args.fUniformHandler->getUniformCStr("
+ "fColorSpaceHelper.gamutXformUniform()) : \"%s\"",
+ default_value(ref.fVariable.fType));
+ } else {
+ var = String::printf("args.fUniformHandler->getUniformCStr(%sVar)",
+ HCodeGenerator::FieldName(name.c_str()).c_str());
+ }
+ String code;
+ if (ref.fVariable.fModifiers.fLayout.fWhen.size()) {
+ code = String::printf("%sVar.isValid() ? %s : \"%s\"",
+ HCodeGenerator::FieldName(name.c_str()).c_str(),
+ var.c_str(),
+ default_value(ref.fVariable.fType));
+ } else {
+ code = var;
+ }
+ fFormatArgs.push_back(code);
+ } else if (SectionAndParameterHelper::IsParameter(ref.fVariable)) {
+ const char* name = ref.fVariable.fName.c_str();
+ this->writeRuntimeValue(ref.fVariable.fType,
+ String::printf("_outer.%s()", name).c_str());
+ } else {
+ this->write(ref.fVariable.fName.c_str());
+ }
+ }
+}
+
+void CPPCodeGenerator::writeFunction(const FunctionDefinition& f) {
+ if (f.fDeclaration.fName == "main") {
+ fFunctionHeader = "";
+ OutputStream* oldOut = fOut;
+ StringStream buffer;
+ fOut = &buffer;
+ for (const auto& s : ((Block&) *f.fBody).fStatements) {
+ this->writeStatement(*s);
+ this->writeLine();
+ }
+
+ fOut = oldOut;
+ this->write(fFunctionHeader);
+ this->write(buffer.str());
+ } else {
+ INHERITED::writeFunction(f);
+ }
+}
+
+void CPPCodeGenerator::writeSetting(const Setting& s) {
+ static constexpr const char* kPrefix = "sk_Args.";
+ if (!strncmp(s.fName.c_str(), kPrefix, strlen(kPrefix))) {
+ const char* name = s.fName.c_str() + strlen(kPrefix);
+ this->writeRuntimeValue(s.fType, HCodeGenerator::FieldName(name).c_str());
+ } else {
+ this->write(s.fName.c_str());
+ }
+}
+
+void CPPCodeGenerator::writeSection(const char* name, const char* prefix) {
+ const auto found = fSectionAndParameterHelper.fSections.find(String(name));
+ if (found != fSectionAndParameterHelper.fSections.end()) {
+ this->writef("%s%s", prefix, found->second->fText.c_str());
+ }
+}
+
+void CPPCodeGenerator::writeProgramElement(const ProgramElement& p) {
+ if (p.fKind == ProgramElement::kSection_Kind) {
+ return;
+ }
+ if (p.fKind == ProgramElement::kVar_Kind) {
+ const VarDeclarations& decls = (const VarDeclarations&) p;
+ if (!decls.fVars.size()) {
+ return;
+ }
+ const Variable& var = *((VarDeclaration&) *decls.fVars[0]).fVar;
+ if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) ||
+ -1 != var.fModifiers.fLayout.fBuiltin) {
+ return;
+ }
+ }
+ INHERITED::writeProgramElement(p);
+}
+
+void CPPCodeGenerator::addUniform(const Variable& var) {
+ if (!needs_uniform_var(var)) {
+ return;
+ }
+ const char* precision;
+ if (var.fModifiers.fFlags & Modifiers::kHighp_Flag) {
+ precision = "kHigh_GrSLPrecision";
+ } else if (var.fModifiers.fFlags & Modifiers::kMediump_Flag) {
+ precision = "kMedium_GrSLPrecision";
+ } else if (var.fModifiers.fFlags & Modifiers::kLowp_Flag) {
+ precision = "kLow_GrSLPrecision";
+ } else {
+ precision = "kDefault_GrSLPrecision";
+ }
+ const char* type;
+ if (var.fType == *fContext.fFloat_Type) {
+ type = "kFloat_GrSLType";
+ } else if (var.fType == *fContext.fVec2_Type) {
+ type = "kVec2f_GrSLType";
+ } else if (var.fType == *fContext.fVec4_Type) {
+ type = "kVec4f_GrSLType";
+ } else if (var.fType == *fContext.fMat4x4_Type ||
+ var.fType == *fContext.fColorSpaceXform_Type) {
+ type = "kMat44f_GrSLType";
+ } else {
+ ABORT("unsupported uniform type: %s %s;\n", var.fType.name().c_str(), var.fName.c_str());
+ }
+ if (var.fModifiers.fLayout.fWhen.size()) {
+ this->writef(" if (%s) {\n ", var.fModifiers.fLayout.fWhen.c_str());
+ }
+ const char* name = var.fName.c_str();
+ this->writef(" %sVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, %s, "
+ "%s, \"%s\");\n", HCodeGenerator::FieldName(name).c_str(), type, precision, name);
+ if (var.fModifiers.fLayout.fWhen.size()) {
+ this->write(" }\n");
+ }
+}
+
+void CPPCodeGenerator::writePrivateVars() {
+ for (const auto& p : fProgram.fElements) {
+ if (ProgramElement::kVar_Kind == p->fKind) {
+ const VarDeclarations* decls = (const VarDeclarations*) p.get();
+ for (const auto& raw : decls->fVars) {
+ VarDeclaration& decl = (VarDeclaration&) *raw;
+ if (is_private(*decl.fVar)) {
+ this->writef("%s %s;\n",
+ HCodeGenerator::FieldType(decl.fVar->fType).c_str(),
+ decl.fVar->fName.c_str());
+ }
+ }
+ }
+ }
+}
+
+void CPPCodeGenerator::writePrivateVarValues() {
+ for (const auto& p : fProgram.fElements) {
+ if (ProgramElement::kVar_Kind == p->fKind) {
+ const VarDeclarations* decls = (const VarDeclarations*) p.get();
+ for (const auto& raw : decls->fVars) {
+ VarDeclaration& decl = (VarDeclaration&) *raw;
+ if (is_private(*decl.fVar) && decl.fValue) {
+ this->writef("%s = %s;\n",
+ decl.fVar->fName.c_str(),
+ decl.fValue->description().c_str());
+ }
+ }
+ }
+ }
+}
+
+bool CPPCodeGenerator::writeEmitCode(std::vector<const Variable*>& uniforms) {
+ this->write(" void emitCode(EmitArgs& args) override {\n"
+ " GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n");
+ this->writef(" const %s& _outer = args.fFp.cast<%s>();\n"
+ " (void) _outer;\n",
+ fFullName.c_str(), fFullName.c_str());
+ this->writePrivateVarValues();
+ for (const auto u : uniforms) {
+ this->addUniform(*u);
+ if (u->fType == *fContext.fColorSpaceXform_Type) {
+ if (fNeedColorSpaceHelper) {
+ fErrors.error(u->fPosition, "only a single ColorSpaceXform is supported");
+ }
+ fNeedColorSpaceHelper = true;
+ this->writef(" fColorSpaceHelper.emitCode(args.fUniformHandler, "
+ "_outer.%s().get());\n",
+ u->fName.c_str());
+ }
+ }
+ this->writeSection(EMIT_CODE_SECTION);
+ OutputStream* old = fOut;
+ StringStream mainBuffer;
+ fOut = &mainBuffer;
+ bool result = INHERITED::generateCode();
+ fOut = old;
+ this->writef("%s fragBuilder->codeAppendf(\"%s\"", fExtraEmitCodeCode.c_str(),
+ mainBuffer.str().c_str());
+ for (const auto& s : fFormatArgs) {
+ this->writef(", %s", s.c_str());
+ }
+ this->write(");\n"
+ " }\n");
+ return result;
+}
+
+void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
+ const char* fullName = fFullName.c_str();
+ auto section = fSectionAndParameterHelper.fSections.find(String(SET_DATA_SECTION));
+ const char* pdman = section != fSectionAndParameterHelper.fSections.end() ?
+ section->second->fArgument.c_str() :
+ "pdman";
+ this->writef(" void onSetData(const GrGLSLProgramDataManager& %s, "
+ "const GrFragmentProcessor& _proc) override {\n",
+ pdman);
+ bool wroteProcessor = false;
+ for (const auto u : uniforms) {
+ if (u->fModifiers.fFlags & Modifiers::kIn_Flag) {
+ if (!wroteProcessor) {
+ this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName, fullName);
+ wroteProcessor = true;
+ this->writef(" {\n");
+ }
+ const char* name = u->fName.c_str();
+ if (u->fType == *fContext.fVec4_Type) {
+ this->writef(" const SkRect %sValue = _outer.%s();\n"
+ " %s.set4fv(%sVar, 4, (float*) &%sValue);\n",
+ name, name, pdman, HCodeGenerator::FieldName(name).c_str(), name);
+ } else if (u->fType == *fContext.fMat4x4_Type) {
+ this->writef(" float %sValue[16];\n"
+ " _outer.%s().asColMajorf(%sValue);\n"
+ " %s.setMatrix4f(%sVar, %sValue);\n",
+ name, name, name, pdman, HCodeGenerator::FieldName(name).c_str(),
+ name);
+ } else if (u->fType == *fContext.fColorSpaceXform_Type) {
+ ASSERT(fNeedColorSpaceHelper);
+ this->writef(" if (fColorSpaceHelper.isValid()) {\n"
+ " fColorSpaceHelper.setData(%s, _outer.%s().get());\n"
+ " }\n",
+ pdman, name);
+ } else {
+ this->writef(" %s.set1f(%sVar, _outer.%s());\n",
+ pdman, HCodeGenerator::FieldName(name).c_str(), name);
+ }
+ }
+ }
+ if (wroteProcessor) {
+ this->writef(" }\n");
+ }
+ if (section != fSectionAndParameterHelper.fSections.end()) {
+ for (const auto& p : fProgram.fElements) {
+ if (ProgramElement::kVar_Kind == p->fKind) {
+ const VarDeclarations* decls = (const VarDeclarations*) p.get();
+ for (const auto& raw : decls->fVars) {
+ VarDeclaration& decl = (VarDeclaration&) *raw;
+ if (needs_uniform_var(*decl.fVar)) {
+ const char* name = decl.fVar->fName.c_str();
+ this->writef(" UniformHandle& %s = %sVar;\n"
+ " (void) %s;\n",
+ name, HCodeGenerator::FieldName(name).c_str(), name);
+ } else if (SectionAndParameterHelper::IsParameter(*decl.fVar)) {
+ const char* name = decl.fVar->fName.c_str();
+ if (!wroteProcessor) {
+ this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName,
+ fullName);
+ wroteProcessor = true;
+ }
+ this->writef(" auto %s = _outer.%s();\n"
+ " (void) %s;\n",
+ name, name, name);
+ }
+ }
+ }
+ }
+ this->writeSection(SET_DATA_SECTION);
+ }
+ this->write(" }\n");
+}
+
+void CPPCodeGenerator::writeTest() {
+ const auto found = fSectionAndParameterHelper.fSections.find(TEST_CODE_SECTION);
+ if (found == fSectionAndParameterHelper.fSections.end()) {
+ return;
+ }
+ const Section* test = found->second;
+ this->writef("GR_DEFINE_FRAGMENT_PROCESSOR_TEST(%s);\n"
+ "#if GR_TEST_UTILS\n"
+ "sk_sp<GrFragmentProcessor> %s::TestCreate(GrProcessorTestData* %s) {\n",
+ fFullName.c_str(),
+ fFullName.c_str(),
+ test->fArgument.c_str());
+ this->writeSection(TEST_CODE_SECTION);
+ this->write("}\n"
+ "#endif\n");
+}
+
+void CPPCodeGenerator::writeGetKey() {
+ this->writef("void %s::onGetGLSLProcessorKey(const GrShaderCaps& caps, "
+ "GrProcessorKeyBuilder* b) const {\n",
+ fFullName.c_str());
+ for (const auto& param : fSectionAndParameterHelper.fParameters) {
+ const char* name = param->fName.c_str();
+ if (param->fType == *fContext.fColorSpaceXform_Type) {
+ this->writef(" b->add32(GrColorSpaceXform::XformKey(%s.get()));\n",
+ HCodeGenerator::FieldName(name).c_str());
+ continue;
+ }
+ if (param->fModifiers.fLayout.fKey != Layout::kNo_Key &&
+ (param->fModifiers.fFlags & Modifiers::kUniform_Flag)) {
+ fErrors.error(param->fPosition,
+ "layout(key) may not be specified on uniforms");
+ }
+ switch (param->fModifiers.fLayout.fKey) {
+ case Layout::kKey_Key:
+ if (param->fType == *fContext.fMat4x4_Type) {
+ ABORT("no automatic key handling for mat4\n");
+ } else if (param->fType == *fContext.fVec2_Type) {
+ this->writef(" b->add32(%s.fX);\n",
+ HCodeGenerator::FieldName(name).c_str());
+ this->writef(" b->add32(%s.fY);\n",
+ HCodeGenerator::FieldName(name).c_str());
+ } else if (param->fType == *fContext.fVec4_Type) {
+ this->writef(" b->add32(%s.x());\n",
+ HCodeGenerator::FieldName(name).c_str());
+ this->writef(" b->add32(%s.y());\n",
+ HCodeGenerator::FieldName(name).c_str());
+ this->writef(" b->add32(%s.width());\n",
+ HCodeGenerator::FieldName(name).c_str());
+ this->writef(" b->add32(%s.height());\n",
+ HCodeGenerator::FieldName(name).c_str());
+ } else {
+ this->writef(" b->add32(%s);\n",
+ HCodeGenerator::FieldName(name).c_str());
+ }
+ break;
+ case Layout::kIdentity_Key:
+ if (param->fType.kind() != Type::kMatrix_Kind) {
+ fErrors.error(param->fPosition,
+ "layout(key=identity) requires matrix type");
+ }
+ this->writef(" b->add32(%s.isIdentity() ? 1 : 0);\n",
+ HCodeGenerator::FieldName(name).c_str());
+ break;
+ case Layout::kNo_Key:
+ break;
+ }
+ }
+ this->write("}\n");
+}
+
+bool CPPCodeGenerator::generateCode() {
+ std::vector<const Variable*> uniforms;
+ for (const auto& p : fProgram.fElements) {
+ if (ProgramElement::kVar_Kind == p->fKind) {
+ const VarDeclarations* decls = (const VarDeclarations*) p.get();
+ for (const auto& raw : decls->fVars) {
+ VarDeclaration& decl = (VarDeclaration&) *raw;
+ if ((decl.fVar->fModifiers.fFlags & Modifiers::kUniform_Flag) &&
+ decl.fVar->fType.kind() != Type::kSampler_Kind) {
+ uniforms.push_back(decl.fVar);
+ }
+ }
+ }
+ }
+ const char* baseName = fName.c_str();
+ const char* fullName = fFullName.c_str();
+ this->writef("/*\n"
+ " * This file was autogenerated from %s.fp.\n"
+ " */\n"
+ "#include \"%s.h\"\n"
+ "#include \"glsl/GrGLSLColorSpaceXformHelper.h\"\n"
+ "#include \"glsl/GrGLSLFragmentProcessor.h\"\n"
+ "#include \"glsl/GrGLSLFragmentShaderBuilder.h\"\n"
+ "#include \"glsl/GrGLSLProgramBuilder.h\"\n"
+ "#include \"GrResourceProvider.h\"\n"
+ "#include \"SkSLCPP.h\"\n"
+ "#include \"SkSLUtil.h\"\n"
+ "class GrGLSL%s : public GrGLSLFragmentProcessor {\n"
+ "public:\n"
+ " GrGLSL%s() {}\n",
+ fullName, fullName, baseName, baseName);
+ bool result = this->writeEmitCode(uniforms);
+ this->write("private:\n");
+ this->writeSetData(uniforms);
+ this->writePrivateVars();
+ for (const auto& u : uniforms) {
+ const char* name = u->fName.c_str();
+ if (needs_uniform_var(*u) && !(u->fModifiers.fFlags & Modifiers::kIn_Flag)) {
+ this->writef(" UniformHandle %sVar;\n", HCodeGenerator::FieldName(name).c_str());
+ }
+ }
+ for (const auto& param : fSectionAndParameterHelper.fParameters) {
+ const char* name = param->fName.c_str();
+ if (needs_uniform_var(*param)) {
+ this->writef(" UniformHandle %sVar;\n", HCodeGenerator::FieldName(name).c_str());
+ }
+ }
+ if (fNeedColorSpaceHelper) {
+ this->write(" GrGLSLColorSpaceXformHelper fColorSpaceHelper;\n");
+ }
+ this->writef("};\n"
+ "GrGLSLFragmentProcessor* %s::onCreateGLSLInstance() const {\n"
+ " return new GrGLSL%s();\n"
+ "}\n",
+ fullName, baseName);
+ this->writeGetKey();
+ this->writef("bool %s::onIsEqual(const GrFragmentProcessor& other) const {\n"
+ " const %s& that = other.cast<%s>();\n"
+ " (void) that;\n",
+ fullName, fullName, fullName);
+ for (const auto& param : fSectionAndParameterHelper.fParameters) {
+ const char* name = param->fName.c_str();
+ this->writef(" if (%s != that.%s) return false;\n",
+ HCodeGenerator::FieldName(name).c_str(),
+ HCodeGenerator::FieldName(name).c_str());
+ }
+ this->write(" return true;\n"
+ "}\n");
+ this->writeSection(CPP_SECTION);
+ this->writeTest();
+ result &= 0 == fErrors.errorCount();
+ return result;
+}
+
+} // namespace