blob: 3f5f2f378ce9dc574e7cc5a1841d104c7bc396aa [file] [log] [blame]
Ethan Nicholas762466e2017-06-29 10:03:38 -04001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/sksl/SkSLHCodeGenerator.h"
Ethan Nicholas762466e2017-06-29 10:03:38 -04009
Brian Osman1298bc42020-06-30 13:39:35 -040010#include "include/private/SkSLSampleUsage.h"
Michael Ludwig8f3a8362020-06-29 17:27:00 -040011#include "src/sksl/SkSLAnalysis.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/sksl/SkSLParser.h"
13#include "src/sksl/SkSLUtil.h"
14#include "src/sksl/ir/SkSLEnum.h"
15#include "src/sksl/ir/SkSLFunctionDeclaration.h"
16#include "src/sksl/ir/SkSLFunctionDefinition.h"
17#include "src/sksl/ir/SkSLSection.h"
18#include "src/sksl/ir/SkSLVarDeclarations.h"
Ethan Nicholas762466e2017-06-29 10:03:38 -040019
Michael Ludwiga4275592018-08-31 10:52:47 -040020#include <set>
21
Ethan Nicholas762466e2017-06-29 10:03:38 -040022namespace SkSL {
23
Ethan Nicholasc9472af2017-10-10 16:30:21 -040024HCodeGenerator::HCodeGenerator(const Context* context, const Program* program,
25 ErrorReporter* errors, String name, OutputStream* out)
Ethan Nicholas762466e2017-06-29 10:03:38 -040026: INHERITED(program, errors, out)
Ethan Nicholasc9472af2017-10-10 16:30:21 -040027, fContext(*context)
Ethan Nicholas762466e2017-06-29 10:03:38 -040028, fName(std::move(name))
29, fFullName(String::printf("Gr%s", fName.c_str()))
Ethan Nicholasd4efe682019-08-29 16:10:13 -040030, fSectionAndParameterHelper(program, *errors) {}
Ethan Nicholas762466e2017-06-29 10:03:38 -040031
Ethan Nicholasd608c092017-10-26 09:30:08 -040032String HCodeGenerator::ParameterType(const Context& context, const Type& type,
33 const Layout& layout) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040034 Layout::CType ctype = ParameterCType(context, type, layout);
35 if (ctype != Layout::CType::kDefault) {
36 return Layout::CTypeToStr(ctype);
37 }
38 return type.name();
39}
40
41Layout::CType HCodeGenerator::ParameterCType(const Context& context, const Type& type,
42 const Layout& layout) {
43 if (layout.fCType != Layout::CType::kDefault) {
Ethan Nicholasd608c092017-10-26 09:30:08 -040044 return layout.fCType;
Ethan Nicholas78aceb22018-08-31 16:13:58 -040045 }
Ethan Nicholasee1c8a72019-02-22 10:50:47 -050046 if (type.kind() == Type::kNullable_Kind) {
47 return ParameterCType(context, type.componentType(), layout);
48 } else if (type == *context.fFloat_Type || type == *context.fHalf_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040049 return Layout::CType::kFloat;
Michael Ludwiga4275592018-08-31 10:52:47 -040050 } else if (type == *context.fInt_Type ||
51 type == *context.fShort_Type ||
52 type == *context.fByte_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040053 return Layout::CType::kInt32;
Ethan Nicholasc9472af2017-10-10 16:30:21 -040054 } else if (type == *context.fFloat2_Type || type == *context.fHalf2_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040055 return Layout::CType::kSkPoint;
Michael Ludwiga4275592018-08-31 10:52:47 -040056 } else if (type == *context.fInt2_Type ||
57 type == *context.fShort2_Type ||
58 type == *context.fByte2_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040059 return Layout::CType::kSkIPoint;
Ruiqi Maob609e6d2018-07-17 10:19:38 -040060 } else if (type == *context.fInt4_Type ||
61 type == *context.fShort4_Type ||
62 type == *context.fByte4_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040063 return Layout::CType::kSkIRect;
Ethan Nicholasc9472af2017-10-10 16:30:21 -040064 } else if (type == *context.fFloat4_Type || type == *context.fHalf4_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040065 return Layout::CType::kSkRect;
Michael Ludwiga4275592018-08-31 10:52:47 -040066 } else if (type == *context.fFloat3x3_Type || type == *context.fHalf3x3_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040067 return Layout::CType::kSkMatrix;
Ethan Nicholasc9472af2017-10-10 16:30:21 -040068 } else if (type == *context.fFloat4x4_Type || type == *context.fHalf4x4_Type) {
Mike Reedb26b4e72020-01-22 14:31:21 -050069 return Layout::CType::kSkM44;
Ethan Nicholas762466e2017-06-29 10:03:38 -040070 } else if (type.kind() == Type::kSampler_Kind) {
Greg Daniel43956122020-02-11 15:49:27 -050071 return Layout::CType::kGrSurfaceProxyView;
Ethan Nicholasc9472af2017-10-10 16:30:21 -040072 } else if (type == *context.fFragmentProcessor_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040073 return Layout::CType::kGrFragmentProcessor;
Ethan Nicholas762466e2017-06-29 10:03:38 -040074 }
Ethan Nicholas78aceb22018-08-31 16:13:58 -040075 return Layout::CType::kDefault;
Ethan Nicholas762466e2017-06-29 10:03:38 -040076}
77
Ethan Nicholasd608c092017-10-26 09:30:08 -040078String HCodeGenerator::FieldType(const Context& context, const Type& type,
79 const Layout& layout) {
Ethan Nicholas762466e2017-06-29 10:03:38 -040080 if (type.kind() == Type::kSampler_Kind) {
81 return "TextureSampler";
Ethan Nicholasc9472af2017-10-10 16:30:21 -040082 } else if (type == *context.fFragmentProcessor_Type) {
83 // we don't store fragment processors in fields, they get registered via
84 // registerChildProcessor instead
Ethan Nicholasd9d33c32018-06-12 11:05:59 -040085 SkASSERT(false);
Ethan Nicholasc9472af2017-10-10 16:30:21 -040086 return "<error>";
Ethan Nicholas762466e2017-06-29 10:03:38 -040087 }
Ethan Nicholasd608c092017-10-26 09:30:08 -040088 return ParameterType(context, type, layout);
Ethan Nicholas762466e2017-06-29 10:03:38 -040089}
90
Michael Ludwiga4275592018-08-31 10:52:47 -040091String HCodeGenerator::AccessType(const Context& context, const Type& type,
92 const Layout& layout) {
Michael Ludwig72efd802018-08-31 13:26:19 -040093 static const std::set<String> primitiveTypes = { "int32_t", "float", "bool", "SkPMColor" };
Michael Ludwiga4275592018-08-31 10:52:47 -040094
95 String fieldType = FieldType(context, type, layout);
96 bool isPrimitive = primitiveTypes.find(fieldType) != primitiveTypes.end();
97 if (isPrimitive) {
98 return fieldType;
99 } else {
100 return String::printf("const %s&", fieldType.c_str());
101 }
102}
103
Ethan Nicholas762466e2017-06-29 10:03:38 -0400104void HCodeGenerator::writef(const char* s, va_list va) {
105 static constexpr int BUFFER_SIZE = 1024;
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400106 va_list copy;
107 va_copy(copy, va);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400108 char buffer[BUFFER_SIZE];
109 int length = vsnprintf(buffer, BUFFER_SIZE, s, va);
110 if (length < BUFFER_SIZE) {
111 fOut->write(buffer, length);
112 } else {
113 std::unique_ptr<char[]> heap(new char[length + 1]);
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400114 vsprintf(heap.get(), s, copy);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400115 fOut->write(heap.get(), length);
116 }
Greg Kaiser27f83022019-02-11 08:32:13 -0800117 va_end(copy);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400118}
119
120void HCodeGenerator::writef(const char* s, ...) {
121 va_list va;
122 va_start(va, s);
123 this->writef(s, va);
124 va_end(va);
125}
126
127bool HCodeGenerator::writeSection(const char* name, const char* prefix) {
Ethan Nicholas68990be2017-07-13 09:36:52 -0400128 const Section* s = fSectionAndParameterHelper.getSection(name);
129 if (s) {
130 this->writef("%s%s", prefix, s->fText.c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400131 return true;
132 }
133 return false;
134}
135
136void HCodeGenerator::writeExtraConstructorParams(const char* separator) {
137 // super-simple parse, just assume the last token before a comma is the name of a parameter
138 // (which is true as long as there are no multi-parameter template types involved). Will replace
139 // this with something more robust if the need arises.
Ethan Nicholas68990be2017-07-13 09:36:52 -0400140 const Section* section = fSectionAndParameterHelper.getSection(CONSTRUCTOR_PARAMS_SECTION);
141 if (section) {
142 const char* s = section->fText.c_str();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400143 #define BUFFER_SIZE 64
144 char lastIdentifier[BUFFER_SIZE];
145 int lastIdentifierLength = 0;
146 bool foundBreak = false;
147 while (*s) {
148 char c = *s;
149 ++s;
150 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
151 c == '_') {
152 if (foundBreak) {
153 lastIdentifierLength = 0;
154 foundBreak = false;
155 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400156 SkASSERT(lastIdentifierLength < BUFFER_SIZE);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400157 lastIdentifier[lastIdentifierLength] = c;
158 ++lastIdentifierLength;
159 } else {
160 foundBreak = true;
161 if (c == ',') {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400162 SkASSERT(lastIdentifierLength < BUFFER_SIZE);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400163 lastIdentifier[lastIdentifierLength] = 0;
164 this->writef("%s%s", separator, lastIdentifier);
165 separator = ", ";
166 } else if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
167 lastIdentifierLength = 0;
168 }
169 }
170 }
171 if (lastIdentifierLength) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400172 SkASSERT(lastIdentifierLength < BUFFER_SIZE);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400173 lastIdentifier[lastIdentifierLength] = 0;
174 this->writef("%s%s", separator, lastIdentifier);
175 }
176 }
177}
178
179void HCodeGenerator::writeMake() {
180 const char* separator;
181 if (!this->writeSection(MAKE_SECTION)) {
Brian Salomonaff329b2017-08-11 09:40:37 -0400182 this->writef(" static std::unique_ptr<GrFragmentProcessor> Make(");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400183 separator = "";
Ethan Nicholas68990be2017-07-13 09:36:52 -0400184 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholasd608c092017-10-26 09:30:08 -0400185 this->writef("%s%s %s", separator, ParameterType(fContext, param->fType,
186 param->fModifiers.fLayout).c_str(),
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700187 String(param->fName).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400188 separator = ", ";
189 }
190 this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator);
191 this->writef(") {\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400192 " return std::unique_ptr<GrFragmentProcessor>(new %s(",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400193 fFullName.c_str());
194 separator = "";
Ethan Nicholas68990be2017-07-13 09:36:52 -0400195 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Greg Daniel43956122020-02-11 15:49:27 -0500196 if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type ||
197 param->fType.nonnullable().kind() == Type::kSampler_Kind) {
Robert Phillips7a59f232017-11-08 15:31:30 -0500198 this->writef("%sstd::move(%s)", separator, String(param->fName).c_str());
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400199 } else {
200 this->writef("%s%s", separator, String(param->fName).c_str());
201 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400202 separator = ", ";
203 }
204 this->writeExtraConstructorParams(separator);
205 this->writef("));\n"
206 " }\n");
207 }
208}
209
Ethan Nicholas68990be2017-07-13 09:36:52 -0400210void HCodeGenerator::failOnSection(const char* section, const char* msg) {
211 std::vector<const Section*> s = fSectionAndParameterHelper.getSections(section);
212 if (s.size()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700213 fErrors.error(s[0]->fOffset, String("@") + section + " " + msg);
Ethan Nicholas68990be2017-07-13 09:36:52 -0400214 }
215}
216
Ethan Nicholas762466e2017-06-29 10:03:38 -0400217void HCodeGenerator::writeConstructor() {
218 if (this->writeSection(CONSTRUCTOR_SECTION)) {
Ethan Nicholas68990be2017-07-13 09:36:52 -0400219 const char* msg = "may not be present when constructor is overridden";
220 this->failOnSection(CONSTRUCTOR_CODE_SECTION, msg);
221 this->failOnSection(CONSTRUCTOR_PARAMS_SECTION, msg);
Ethan Nicholas68990be2017-07-13 09:36:52 -0400222 this->failOnSection(INITIALIZERS_SECTION, msg);
223 this->failOnSection(OPTIMIZATION_FLAGS_SECTION, msg);
Robert Phillips1e8501e2018-03-23 15:00:20 -0400224 return;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400225 }
226 this->writef(" %s(", fFullName.c_str());
227 const char* separator = "";
Ethan Nicholas68990be2017-07-13 09:36:52 -0400228 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholasd608c092017-10-26 09:30:08 -0400229 this->writef("%s%s %s", separator, ParameterType(fContext, param->fType,
230 param->fModifiers.fLayout).c_str(),
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700231 String(param->fName).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400232 separator = ", ";
233 }
234 this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator);
235 this->writef(")\n"
Ethan Nicholasabff9562017-10-09 10:54:08 -0400236 " : INHERITED(k%s_ClassID", fFullName.c_str());
237 if (!this->writeSection(OPTIMIZATION_FLAGS_SECTION, ", (OptimizationFlags) ")) {
238 this->writef(", kNone_OptimizationFlags");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400239 }
240 this->writef(")");
241 this->writeSection(INITIALIZERS_SECTION, "\n , ");
Ethan Nicholas68990be2017-07-13 09:36:52 -0400242 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700243 String nameString(param->fName);
244 const char* name = nameString.c_str();
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500245 const Type& type = param->fType.nonnullable();
246 if (type.kind() == Type::kSampler_Kind) {
Ethan Nicholas68990be2017-07-13 09:36:52 -0400247 this->writef("\n , %s(std::move(%s)", FieldName(name).c_str(), name);
248 for (const Section* s : fSectionAndParameterHelper.getSections(
249 SAMPLER_PARAMS_SECTION)) {
250 if (s->fArgument == name) {
251 this->writef(", %s", s->fText.c_str());
252 }
253 }
254 this->writef(")");
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500255 } else if (type == *fContext.fFragmentProcessor_Type) {
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400256 // do nothing
Ethan Nicholas762466e2017-06-29 10:03:38 -0400257 } else {
258 this->writef("\n , %s(%s)", FieldName(name).c_str(), name);
259 }
260 }
261 this->writef(" {\n");
262 this->writeSection(CONSTRUCTOR_CODE_SECTION);
Michael Ludwige88320b2020-06-24 09:04:56 -0400263
Michael Ludwig8f3a8362020-06-29 17:27:00 -0400264 if (Analysis::ReferencesSampleCoords(fProgram)) {
Michael Ludwige88320b2020-06-24 09:04:56 -0400265 this->writef(" this->setUsesSampleCoordsDirectly();\n");
266 }
267
Brian Salomonf7dcd762018-07-30 14:48:15 -0400268 int samplerCount = 0;
John Stiles88183902020-06-10 16:40:38 -0400269 for (const Variable* param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400270 if (param->fType.kind() == Type::kSampler_Kind) {
Brian Salomonf7dcd762018-07-30 14:48:15 -0400271 ++samplerCount;
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500272 } else if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
273 if (param->fType.kind() == Type::kNullable_Kind) {
274 this->writef(" if (%s) {\n", String(param->fName).c_str());
275 } else {
276 this->writef(" SkASSERT(%s);", String(param->fName).c_str());
277 }
Michael Ludwig9aba6252020-06-22 14:46:36 -0400278
Brian Osman1298bc42020-06-30 13:39:35 -0400279 SampleUsage usage = Analysis::GetSampleUsage(fProgram, *param);
Michael Ludwig9aba6252020-06-22 14:46:36 -0400280
Brian Osman1298bc42020-06-30 13:39:35 -0400281 std::string perspExpression;
282 if (usage.hasUniformMatrix()) {
283 for (const Variable* p : fSectionAndParameterHelper.getParameters()) {
284 if ((p->fModifiers.fFlags & Modifiers::kIn_Flag) &&
285 usage.fExpression == String(p->fName)) {
286 perspExpression = usage.fExpression + ".hasPerspective()";
Michael Ludwig9aba6252020-06-22 14:46:36 -0400287 break;
Brian Osman1298bc42020-06-30 13:39:35 -0400288 }
Michael Ludwig9aba6252020-06-22 14:46:36 -0400289 }
Ethan Nicholasafe2c902020-04-28 13:55:02 -0400290 }
Brian Osman1298bc42020-06-30 13:39:35 -0400291 std::string usageArg = usage.constructor(std::move(perspExpression));
Michael Ludwig9aba6252020-06-22 14:46:36 -0400292
Brian Osman1298bc42020-06-30 13:39:35 -0400293 this->writef(" %s_index = this->registerChild(std::move(%s), %s);",
John Stiles88183902020-06-10 16:40:38 -0400294 FieldName(String(param->fName).c_str()).c_str(),
Michael Ludwig9aba6252020-06-22 14:46:36 -0400295 String(param->fName).c_str(),
Brian Osman1298bc42020-06-30 13:39:35 -0400296 usageArg.c_str());
Michael Ludwig9aba6252020-06-22 14:46:36 -0400297
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500298 if (param->fType.kind() == Type::kNullable_Kind) {
299 this->writef(" }");
300 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400301 }
302 }
Brian Salomonf7dcd762018-07-30 14:48:15 -0400303 if (samplerCount) {
304 this->writef(" this->setTextureSamplerCnt(%d);", samplerCount);
305 }
Ethan Nicholasabff9562017-10-09 10:54:08 -0400306 this->writef(" }\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400307}
308
309void HCodeGenerator::writeFields() {
310 this->writeSection(FIELDS_SECTION);
Ethan Nicholas68990be2017-07-13 09:36:52 -0400311 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500312 String name = FieldName(String(param->fName).c_str());
313 if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
314 this->writef(" int %s_index = -1;\n", name.c_str());
315 } else {
316 this->writef(" %s %s;\n", FieldType(fContext, param->fType,
317 param->fModifiers.fLayout).c_str(),
318 name.c_str());
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400319 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400320 }
321}
322
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500323String HCodeGenerator::GetHeader(const Program& program, ErrorReporter& errors) {
324 SymbolTable types(&errors);
325 Parser parser(program.fSource->c_str(), program.fSource->length(), types, errors);
326 for (;;) {
327 Token header = parser.nextRawToken();
328 switch (header.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400329 case Token::Kind::TK_WHITESPACE:
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500330 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400331 case Token::Kind::TK_BLOCK_COMMENT:
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500332 return String(program.fSource->c_str() + header.fOffset, header.fLength);
333 default:
334 return "";
335 }
336 }
337}
338
Ethan Nicholas762466e2017-06-29 10:03:38 -0400339bool HCodeGenerator::generateCode() {
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500340 this->writef("%s\n", GetHeader(fProgram, fErrors).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400341 this->writef(kFragmentProcessorHeader, fFullName.c_str());
342 this->writef("#ifndef %s_DEFINED\n"
John Stiles88183902020-06-10 16:40:38 -0400343 "#define %s_DEFINED\n"
344 "\n",
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400345 fFullName.c_str(),
346 fFullName.c_str());
John Stiles88183902020-06-10 16:40:38 -0400347 this->writef("#include \"include/core/SkM44.h\"\n"
348 "#include \"include/core/SkTypes.h\"\n"
349 "\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400350 this->writeSection(HEADER_SECTION);
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500351 this->writef("\n"
John Stiles88183902020-06-10 16:40:38 -0400352 "#include \"src/gpu/GrFragmentProcessor.h\"\n"
353 "\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400354 this->writef("class %s : public GrFragmentProcessor {\n"
355 "public:\n",
356 fFullName.c_str());
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400357 for (const auto& p : fProgram) {
358 if (ProgramElement::kEnum_Kind == p.fKind && !((Enum&) p).fBuiltin) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -0500359 this->writef("%s\n", ((Enum&) p).code().c_str());
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500360 }
361 }
Ethan Nicholase9d172a2017-11-20 12:12:24 -0500362 this->writeSection(CLASS_SECTION);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400363 this->writeMake();
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400364 this->writef(" %s(const %s& src);\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400365 " std::unique_ptr<GrFragmentProcessor> clone() const override;\n"
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400366 " const char* name() const override { return \"%s\"; }\n",
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400367 fFullName.c_str(), fFullName.c_str(), fName.c_str());
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400368 this->writeFields();
369 this->writef("private:\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400370 this->writeConstructor();
371 this->writef(" GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n"
372 " void onGetGLSLProcessorKey(const GrShaderCaps&,"
373 "GrProcessorKeyBuilder*) const override;\n"
Brian Salomonf7dcd762018-07-30 14:48:15 -0400374 " bool onIsEqual(const GrFragmentProcessor&) const override;\n");
375 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
376 if (param->fType.kind() == Type::kSampler_Kind) {
377 this->writef(" const TextureSampler& onTextureSampler(int) const override;");
378 break;
379 }
380 }
381 this->writef(" GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400382 this->writef(" typedef GrFragmentProcessor INHERITED;\n"
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400383 "};\n");
384 this->writeSection(HEADER_END_SECTION);
Greg Daniel3e8c3452018-04-06 10:37:55 -0400385 this->writef("#endif\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400386 return 0 == fErrors.errorCount();
387}
388
389} // namespace