blob: c28431558ea06fd3d0ce57dcdff2e4abd0ea609c [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/sksl/SkSLParser.h"
11#include "src/sksl/SkSLUtil.h"
12#include "src/sksl/ir/SkSLEnum.h"
13#include "src/sksl/ir/SkSLFunctionDeclaration.h"
14#include "src/sksl/ir/SkSLFunctionDefinition.h"
15#include "src/sksl/ir/SkSLSection.h"
16#include "src/sksl/ir/SkSLVarDeclarations.h"
Ethan Nicholas762466e2017-06-29 10:03:38 -040017
Michael Ludwiga4275592018-08-31 10:52:47 -040018#include <set>
19
Ethan Nicholas762466e2017-06-29 10:03:38 -040020namespace SkSL {
21
Ethan Nicholasc9472af2017-10-10 16:30:21 -040022HCodeGenerator::HCodeGenerator(const Context* context, const Program* program,
23 ErrorReporter* errors, String name, OutputStream* out)
Ethan Nicholas762466e2017-06-29 10:03:38 -040024: INHERITED(program, errors, out)
Ethan Nicholasc9472af2017-10-10 16:30:21 -040025, fContext(*context)
Ethan Nicholas762466e2017-06-29 10:03:38 -040026, fName(std::move(name))
27, fFullName(String::printf("Gr%s", fName.c_str()))
Ethan Nicholasd4efe682019-08-29 16:10:13 -040028, fSectionAndParameterHelper(program, *errors) {}
Ethan Nicholas762466e2017-06-29 10:03:38 -040029
Ethan Nicholasd608c092017-10-26 09:30:08 -040030String HCodeGenerator::ParameterType(const Context& context, const Type& type,
31 const Layout& layout) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040032 Layout::CType ctype = ParameterCType(context, type, layout);
33 if (ctype != Layout::CType::kDefault) {
34 return Layout::CTypeToStr(ctype);
35 }
36 return type.name();
37}
38
39Layout::CType HCodeGenerator::ParameterCType(const Context& context, const Type& type,
40 const Layout& layout) {
41 if (layout.fCType != Layout::CType::kDefault) {
Ethan Nicholasd608c092017-10-26 09:30:08 -040042 return layout.fCType;
Ethan Nicholas78aceb22018-08-31 16:13:58 -040043 }
Ethan Nicholasee1c8a72019-02-22 10:50:47 -050044 if (type.kind() == Type::kNullable_Kind) {
45 return ParameterCType(context, type.componentType(), layout);
46 } else if (type == *context.fFloat_Type || type == *context.fHalf_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040047 return Layout::CType::kFloat;
Michael Ludwiga4275592018-08-31 10:52:47 -040048 } else if (type == *context.fInt_Type ||
49 type == *context.fShort_Type ||
50 type == *context.fByte_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040051 return Layout::CType::kInt32;
Ethan Nicholasc9472af2017-10-10 16:30:21 -040052 } else if (type == *context.fFloat2_Type || type == *context.fHalf2_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040053 return Layout::CType::kSkPoint;
Michael Ludwiga4275592018-08-31 10:52:47 -040054 } else if (type == *context.fInt2_Type ||
55 type == *context.fShort2_Type ||
56 type == *context.fByte2_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040057 return Layout::CType::kSkIPoint;
Ruiqi Maob609e6d2018-07-17 10:19:38 -040058 } else if (type == *context.fInt4_Type ||
59 type == *context.fShort4_Type ||
60 type == *context.fByte4_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040061 return Layout::CType::kSkIRect;
Ethan Nicholasc9472af2017-10-10 16:30:21 -040062 } else if (type == *context.fFloat4_Type || type == *context.fHalf4_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040063 return Layout::CType::kSkRect;
Michael Ludwiga4275592018-08-31 10:52:47 -040064 } else if (type == *context.fFloat3x3_Type || type == *context.fHalf3x3_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040065 return Layout::CType::kSkMatrix;
Ethan Nicholasc9472af2017-10-10 16:30:21 -040066 } else if (type == *context.fFloat4x4_Type || type == *context.fHalf4x4_Type) {
Mike Reedb26b4e72020-01-22 14:31:21 -050067 return Layout::CType::kSkM44;
Ethan Nicholas762466e2017-06-29 10:03:38 -040068 } else if (type.kind() == Type::kSampler_Kind) {
Michael Ludwig8fa469d2019-11-25 16:08:44 -050069 return Layout::CType::kGrSurfaceProxy;
Ethan Nicholasc9472af2017-10-10 16:30:21 -040070 } else if (type == *context.fFragmentProcessor_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040071 return Layout::CType::kGrFragmentProcessor;
Ethan Nicholas762466e2017-06-29 10:03:38 -040072 }
Ethan Nicholas78aceb22018-08-31 16:13:58 -040073 return Layout::CType::kDefault;
Ethan Nicholas762466e2017-06-29 10:03:38 -040074}
75
Ethan Nicholasd608c092017-10-26 09:30:08 -040076String HCodeGenerator::FieldType(const Context& context, const Type& type,
77 const Layout& layout) {
Ethan Nicholas762466e2017-06-29 10:03:38 -040078 if (type.kind() == Type::kSampler_Kind) {
79 return "TextureSampler";
Ethan Nicholasc9472af2017-10-10 16:30:21 -040080 } else if (type == *context.fFragmentProcessor_Type) {
81 // we don't store fragment processors in fields, they get registered via
82 // registerChildProcessor instead
Ethan Nicholasd9d33c32018-06-12 11:05:59 -040083 SkASSERT(false);
Ethan Nicholasc9472af2017-10-10 16:30:21 -040084 return "<error>";
Ethan Nicholas762466e2017-06-29 10:03:38 -040085 }
Ethan Nicholasd608c092017-10-26 09:30:08 -040086 return ParameterType(context, type, layout);
Ethan Nicholas762466e2017-06-29 10:03:38 -040087}
88
Michael Ludwiga4275592018-08-31 10:52:47 -040089String HCodeGenerator::AccessType(const Context& context, const Type& type,
90 const Layout& layout) {
Michael Ludwig72efd802018-08-31 13:26:19 -040091 static const std::set<String> primitiveTypes = { "int32_t", "float", "bool", "SkPMColor" };
Michael Ludwiga4275592018-08-31 10:52:47 -040092
93 String fieldType = FieldType(context, type, layout);
94 bool isPrimitive = primitiveTypes.find(fieldType) != primitiveTypes.end();
95 if (isPrimitive) {
96 return fieldType;
97 } else {
98 return String::printf("const %s&", fieldType.c_str());
99 }
100}
101
Ethan Nicholas762466e2017-06-29 10:03:38 -0400102void HCodeGenerator::writef(const char* s, va_list va) {
103 static constexpr int BUFFER_SIZE = 1024;
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400104 va_list copy;
105 va_copy(copy, va);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400106 char buffer[BUFFER_SIZE];
107 int length = vsnprintf(buffer, BUFFER_SIZE, s, va);
108 if (length < BUFFER_SIZE) {
109 fOut->write(buffer, length);
110 } else {
111 std::unique_ptr<char[]> heap(new char[length + 1]);
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400112 vsprintf(heap.get(), s, copy);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400113 fOut->write(heap.get(), length);
114 }
Greg Kaiser27f83022019-02-11 08:32:13 -0800115 va_end(copy);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400116}
117
118void HCodeGenerator::writef(const char* s, ...) {
119 va_list va;
120 va_start(va, s);
121 this->writef(s, va);
122 va_end(va);
123}
124
125bool HCodeGenerator::writeSection(const char* name, const char* prefix) {
Ethan Nicholas68990be2017-07-13 09:36:52 -0400126 const Section* s = fSectionAndParameterHelper.getSection(name);
127 if (s) {
128 this->writef("%s%s", prefix, s->fText.c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400129 return true;
130 }
131 return false;
132}
133
134void HCodeGenerator::writeExtraConstructorParams(const char* separator) {
135 // super-simple parse, just assume the last token before a comma is the name of a parameter
136 // (which is true as long as there are no multi-parameter template types involved). Will replace
137 // this with something more robust if the need arises.
Ethan Nicholas68990be2017-07-13 09:36:52 -0400138 const Section* section = fSectionAndParameterHelper.getSection(CONSTRUCTOR_PARAMS_SECTION);
139 if (section) {
140 const char* s = section->fText.c_str();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400141 #define BUFFER_SIZE 64
142 char lastIdentifier[BUFFER_SIZE];
143 int lastIdentifierLength = 0;
144 bool foundBreak = false;
145 while (*s) {
146 char c = *s;
147 ++s;
148 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
149 c == '_') {
150 if (foundBreak) {
151 lastIdentifierLength = 0;
152 foundBreak = false;
153 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400154 SkASSERT(lastIdentifierLength < BUFFER_SIZE);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400155 lastIdentifier[lastIdentifierLength] = c;
156 ++lastIdentifierLength;
157 } else {
158 foundBreak = true;
159 if (c == ',') {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400160 SkASSERT(lastIdentifierLength < BUFFER_SIZE);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400161 lastIdentifier[lastIdentifierLength] = 0;
162 this->writef("%s%s", separator, lastIdentifier);
163 separator = ", ";
164 } else if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
165 lastIdentifierLength = 0;
166 }
167 }
168 }
169 if (lastIdentifierLength) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400170 SkASSERT(lastIdentifierLength < BUFFER_SIZE);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400171 lastIdentifier[lastIdentifierLength] = 0;
172 this->writef("%s%s", separator, lastIdentifier);
173 }
174 }
175}
176
177void HCodeGenerator::writeMake() {
178 const char* separator;
179 if (!this->writeSection(MAKE_SECTION)) {
Brian Salomonaff329b2017-08-11 09:40:37 -0400180 this->writef(" static std::unique_ptr<GrFragmentProcessor> Make(");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400181 separator = "";
Ethan Nicholas68990be2017-07-13 09:36:52 -0400182 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholasd608c092017-10-26 09:30:08 -0400183 this->writef("%s%s %s", separator, ParameterType(fContext, param->fType,
184 param->fModifiers.fLayout).c_str(),
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700185 String(param->fName).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400186 separator = ", ";
187 }
188 this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator);
189 this->writef(") {\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400190 " return std::unique_ptr<GrFragmentProcessor>(new %s(",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400191 fFullName.c_str());
192 separator = "";
Ethan Nicholas68990be2017-07-13 09:36:52 -0400193 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500194 if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
Robert Phillips7a59f232017-11-08 15:31:30 -0500195 this->writef("%sstd::move(%s)", separator, String(param->fName).c_str());
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400196 } else {
197 this->writef("%s%s", separator, String(param->fName).c_str());
198 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400199 separator = ", ";
200 }
201 this->writeExtraConstructorParams(separator);
202 this->writef("));\n"
203 " }\n");
204 }
205}
206
Ethan Nicholas68990be2017-07-13 09:36:52 -0400207void HCodeGenerator::failOnSection(const char* section, const char* msg) {
208 std::vector<const Section*> s = fSectionAndParameterHelper.getSections(section);
209 if (s.size()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700210 fErrors.error(s[0]->fOffset, String("@") + section + " " + msg);
Ethan Nicholas68990be2017-07-13 09:36:52 -0400211 }
212}
213
Ethan Nicholas762466e2017-06-29 10:03:38 -0400214void HCodeGenerator::writeConstructor() {
215 if (this->writeSection(CONSTRUCTOR_SECTION)) {
Ethan Nicholas68990be2017-07-13 09:36:52 -0400216 const char* msg = "may not be present when constructor is overridden";
217 this->failOnSection(CONSTRUCTOR_CODE_SECTION, msg);
218 this->failOnSection(CONSTRUCTOR_PARAMS_SECTION, msg);
Ethan Nicholas68990be2017-07-13 09:36:52 -0400219 this->failOnSection(INITIALIZERS_SECTION, msg);
220 this->failOnSection(OPTIMIZATION_FLAGS_SECTION, msg);
Robert Phillips1e8501e2018-03-23 15:00:20 -0400221 return;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400222 }
223 this->writef(" %s(", fFullName.c_str());
224 const char* separator = "";
Ethan Nicholas68990be2017-07-13 09:36:52 -0400225 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholasd608c092017-10-26 09:30:08 -0400226 this->writef("%s%s %s", separator, ParameterType(fContext, param->fType,
227 param->fModifiers.fLayout).c_str(),
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700228 String(param->fName).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400229 separator = ", ";
230 }
231 this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator);
232 this->writef(")\n"
Ethan Nicholasabff9562017-10-09 10:54:08 -0400233 " : INHERITED(k%s_ClassID", fFullName.c_str());
234 if (!this->writeSection(OPTIMIZATION_FLAGS_SECTION, ", (OptimizationFlags) ")) {
235 this->writef(", kNone_OptimizationFlags");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400236 }
237 this->writef(")");
238 this->writeSection(INITIALIZERS_SECTION, "\n , ");
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400239 const auto transforms = fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION);
240 for (size_t i = 0; i < transforms.size(); ++i) {
241 const Section& s = *transforms[i];
242 String field = CoordTransformName(s.fArgument.c_str(), i);
243 if (s.fArgument.size()) {
244 this->writef("\n , %s(%s, %s.get())", field.c_str(), s.fText.c_str(),
245 FieldName(s.fArgument.c_str()).c_str());
246 }
247 else {
248 this->writef("\n , %s(%s)", field.c_str(), s.fText.c_str());
249 }
250 }
Ethan Nicholas68990be2017-07-13 09:36:52 -0400251 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700252 String nameString(param->fName);
253 const char* name = nameString.c_str();
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500254 const Type& type = param->fType.nonnullable();
255 if (type.kind() == Type::kSampler_Kind) {
Ethan Nicholas68990be2017-07-13 09:36:52 -0400256 this->writef("\n , %s(std::move(%s)", FieldName(name).c_str(), name);
257 for (const Section* s : fSectionAndParameterHelper.getSections(
258 SAMPLER_PARAMS_SECTION)) {
259 if (s->fArgument == name) {
260 this->writef(", %s", s->fText.c_str());
261 }
262 }
263 this->writef(")");
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500264 } else if (type == *fContext.fFragmentProcessor_Type) {
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400265 // do nothing
Ethan Nicholas762466e2017-06-29 10:03:38 -0400266 } else {
267 this->writef("\n , %s(%s)", FieldName(name).c_str(), name);
268 }
269 }
270 this->writef(" {\n");
271 this->writeSection(CONSTRUCTOR_CODE_SECTION);
Brian Salomonf7dcd762018-07-30 14:48:15 -0400272 int samplerCount = 0;
Ethan Nicholas68990be2017-07-13 09:36:52 -0400273 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400274 if (param->fType.kind() == Type::kSampler_Kind) {
Brian Salomonf7dcd762018-07-30 14:48:15 -0400275 ++samplerCount;
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500276 } else if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
277 if (param->fType.kind() == Type::kNullable_Kind) {
278 this->writef(" if (%s) {\n", String(param->fName).c_str());
279 } else {
280 this->writef(" SkASSERT(%s);", String(param->fName).c_str());
281 }
282 this->writef(" %s_index = this->numChildProcessors();",
283 FieldName(String(param->fName).c_str()).c_str());
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400284 if (fSectionAndParameterHelper.hasCoordOverrides(*param)) {
Brian Salomon7d8b3972019-11-26 22:34:44 -0500285 this->writef(" %s->setSampledWithExplicitCoords(true);",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400286 String(param->fName).c_str());
287 }
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500288 this->writef(" this->registerChildProcessor(std::move(%s));",
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400289 String(param->fName).c_str());
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500290 if (param->fType.kind() == Type::kNullable_Kind) {
291 this->writef(" }");
292 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400293 }
294 }
Brian Salomonf7dcd762018-07-30 14:48:15 -0400295 if (samplerCount) {
296 this->writef(" this->setTextureSamplerCnt(%d);", samplerCount);
297 }
Ethan Nicholas929a6812018-08-06 14:56:59 -0400298 for (size_t i = 0; i < transforms.size(); ++i) {
299 const Section& s = *transforms[i];
300 String field = CoordTransformName(s.fArgument.c_str(), i);
301 this->writef(" this->addCoordTransform(&%s);\n", field.c_str());
Ethan Nicholas68990be2017-07-13 09:36:52 -0400302 }
Ethan Nicholasabff9562017-10-09 10:54:08 -0400303 this->writef(" }\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400304}
305
306void HCodeGenerator::writeFields() {
307 this->writeSection(FIELDS_SECTION);
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400308 const auto transforms = fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION);
309 for (size_t i = 0; i < transforms.size(); ++i) {
310 const Section& s = *transforms[i];
311 this->writef(" GrCoordTransform %s;\n",
312 CoordTransformName(s.fArgument.c_str(), i).c_str());
313 }
Ethan Nicholas68990be2017-07-13 09:36:52 -0400314 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500315 String name = FieldName(String(param->fName).c_str());
316 if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
317 this->writef(" int %s_index = -1;\n", name.c_str());
318 } else {
319 this->writef(" %s %s;\n", FieldType(fContext, param->fType,
320 param->fModifiers.fLayout).c_str(),
321 name.c_str());
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400322 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400323 }
324}
325
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500326String HCodeGenerator::GetHeader(const Program& program, ErrorReporter& errors) {
327 SymbolTable types(&errors);
328 Parser parser(program.fSource->c_str(), program.fSource->length(), types, errors);
329 for (;;) {
330 Token header = parser.nextRawToken();
331 switch (header.fKind) {
332 case Token::WHITESPACE:
333 break;
334 case Token::BLOCK_COMMENT:
335 return String(program.fSource->c_str() + header.fOffset, header.fLength);
336 default:
337 return "";
338 }
339 }
340}
341
Ethan Nicholas762466e2017-06-29 10:03:38 -0400342bool HCodeGenerator::generateCode() {
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500343 this->writef("%s\n", GetHeader(fProgram, fErrors).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400344 this->writef(kFragmentProcessorHeader, fFullName.c_str());
345 this->writef("#ifndef %s_DEFINED\n"
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400346 "#define %s_DEFINED\n",
347 fFullName.c_str(),
348 fFullName.c_str());
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500349 this->writef("#include \"include/core/SkTypes.h\"\n");
Mike Reedb26b4e72020-01-22 14:31:21 -0500350 this->writef("#include \"include/private/SkM44.h\"\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400351 this->writeSection(HEADER_SECTION);
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500352 this->writef("\n"
353 "#include \"src/gpu/GrCoordTransform.h\"\n"
354 "#include \"src/gpu/GrFragmentProcessor.h\"\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400355 this->writef("class %s : public GrFragmentProcessor {\n"
356 "public:\n",
357 fFullName.c_str());
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400358 for (const auto& p : fProgram) {
359 if (ProgramElement::kEnum_Kind == p.fKind && !((Enum&) p).fBuiltin) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -0500360 this->writef("%s\n", ((Enum&) p).code().c_str());
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500361 }
362 }
Ethan Nicholase9d172a2017-11-20 12:12:24 -0500363 this->writeSection(CLASS_SECTION);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400364 this->writeMake();
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400365 this->writef(" %s(const %s& src);\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400366 " std::unique_ptr<GrFragmentProcessor> clone() const override;\n"
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400367 " const char* name() const override { return \"%s\"; }\n",
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400368 fFullName.c_str(), fFullName.c_str(), fName.c_str());
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400369 this->writeFields();
370 this->writef("private:\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400371 this->writeConstructor();
372 this->writef(" GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n"
373 " void onGetGLSLProcessorKey(const GrShaderCaps&,"
374 "GrProcessorKeyBuilder*) const override;\n"
Brian Salomonf7dcd762018-07-30 14:48:15 -0400375 " bool onIsEqual(const GrFragmentProcessor&) const override;\n");
376 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
377 if (param->fType.kind() == Type::kSampler_Kind) {
378 this->writef(" const TextureSampler& onTextureSampler(int) const override;");
379 break;
380 }
381 }
382 this->writef(" GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400383 this->writef(" typedef GrFragmentProcessor INHERITED;\n"
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400384 "};\n");
385 this->writeSection(HEADER_END_SECTION);
Greg Daniel3e8c3452018-04-06 10:37:55 -0400386 this->writef("#endif\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400387 return 0 == fErrors.errorCount();
388}
389
390} // namespace