blob: 012b302481098432b5772e9bb2d940cba9864101 [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 Nicholas2a479a52020-08-18 16:29:45 -040022#if defined(SKSL_STANDALONE) || defined(GR_TEST_UTILS)
23
Ethan Nicholas762466e2017-06-29 10:03:38 -040024namespace SkSL {
25
Ethan Nicholasc9472af2017-10-10 16:30:21 -040026HCodeGenerator::HCodeGenerator(const Context* context, const Program* program,
27 ErrorReporter* errors, String name, OutputStream* out)
Ethan Nicholas762466e2017-06-29 10:03:38 -040028: INHERITED(program, errors, out)
Ethan Nicholasc9472af2017-10-10 16:30:21 -040029, fContext(*context)
Ethan Nicholas762466e2017-06-29 10:03:38 -040030, fName(std::move(name))
31, fFullName(String::printf("Gr%s", fName.c_str()))
Ethan Nicholasd4efe682019-08-29 16:10:13 -040032, fSectionAndParameterHelper(program, *errors) {}
Ethan Nicholas762466e2017-06-29 10:03:38 -040033
Ethan Nicholasd608c092017-10-26 09:30:08 -040034String HCodeGenerator::ParameterType(const Context& context, const Type& type,
35 const Layout& layout) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040036 Layout::CType ctype = ParameterCType(context, type, layout);
37 if (ctype != Layout::CType::kDefault) {
38 return Layout::CTypeToStr(ctype);
39 }
40 return type.name();
41}
42
43Layout::CType HCodeGenerator::ParameterCType(const Context& context, const Type& type,
44 const Layout& layout) {
45 if (layout.fCType != Layout::CType::kDefault) {
Ethan Nicholasd608c092017-10-26 09:30:08 -040046 return layout.fCType;
Ethan Nicholas78aceb22018-08-31 16:13:58 -040047 }
Ethan Nicholasee1c8a72019-02-22 10:50:47 -050048 if (type.kind() == Type::kNullable_Kind) {
49 return ParameterCType(context, type.componentType(), layout);
50 } else if (type == *context.fFloat_Type || type == *context.fHalf_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040051 return Layout::CType::kFloat;
Michael Ludwiga4275592018-08-31 10:52:47 -040052 } else if (type == *context.fInt_Type ||
53 type == *context.fShort_Type ||
54 type == *context.fByte_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040055 return Layout::CType::kInt32;
Ethan Nicholasc9472af2017-10-10 16:30:21 -040056 } else if (type == *context.fFloat2_Type || type == *context.fHalf2_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040057 return Layout::CType::kSkPoint;
Michael Ludwiga4275592018-08-31 10:52:47 -040058 } else if (type == *context.fInt2_Type ||
59 type == *context.fShort2_Type ||
60 type == *context.fByte2_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040061 return Layout::CType::kSkIPoint;
Ruiqi Maob609e6d2018-07-17 10:19:38 -040062 } else if (type == *context.fInt4_Type ||
63 type == *context.fShort4_Type ||
64 type == *context.fByte4_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040065 return Layout::CType::kSkIRect;
Ethan Nicholasc9472af2017-10-10 16:30:21 -040066 } else if (type == *context.fFloat4_Type || type == *context.fHalf4_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040067 return Layout::CType::kSkRect;
Michael Ludwiga4275592018-08-31 10:52:47 -040068 } else if (type == *context.fFloat3x3_Type || type == *context.fHalf3x3_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040069 return Layout::CType::kSkMatrix;
Ethan Nicholasc9472af2017-10-10 16:30:21 -040070 } else if (type == *context.fFloat4x4_Type || type == *context.fHalf4x4_Type) {
Mike Reedb26b4e72020-01-22 14:31:21 -050071 return Layout::CType::kSkM44;
Ethan Nicholas762466e2017-06-29 10:03:38 -040072 } else if (type.kind() == Type::kSampler_Kind) {
Greg Daniel43956122020-02-11 15:49:27 -050073 return Layout::CType::kGrSurfaceProxyView;
Ethan Nicholasc9472af2017-10-10 16:30:21 -040074 } else if (type == *context.fFragmentProcessor_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040075 return Layout::CType::kGrFragmentProcessor;
Ethan Nicholas762466e2017-06-29 10:03:38 -040076 }
Ethan Nicholas78aceb22018-08-31 16:13:58 -040077 return Layout::CType::kDefault;
Ethan Nicholas762466e2017-06-29 10:03:38 -040078}
79
Ethan Nicholasd608c092017-10-26 09:30:08 -040080String HCodeGenerator::FieldType(const Context& context, const Type& type,
81 const Layout& layout) {
Ethan Nicholas762466e2017-06-29 10:03:38 -040082 if (type.kind() == Type::kSampler_Kind) {
83 return "TextureSampler";
Ethan Nicholasc9472af2017-10-10 16:30:21 -040084 } else if (type == *context.fFragmentProcessor_Type) {
85 // we don't store fragment processors in fields, they get registered via
86 // registerChildProcessor instead
Ethan Nicholasd9d33c32018-06-12 11:05:59 -040087 SkASSERT(false);
Ethan Nicholasc9472af2017-10-10 16:30:21 -040088 return "<error>";
Ethan Nicholas762466e2017-06-29 10:03:38 -040089 }
Ethan Nicholasd608c092017-10-26 09:30:08 -040090 return ParameterType(context, type, layout);
Ethan Nicholas762466e2017-06-29 10:03:38 -040091}
92
Michael Ludwiga4275592018-08-31 10:52:47 -040093String HCodeGenerator::AccessType(const Context& context, const Type& type,
94 const Layout& layout) {
Michael Ludwig72efd802018-08-31 13:26:19 -040095 static const std::set<String> primitiveTypes = { "int32_t", "float", "bool", "SkPMColor" };
Michael Ludwiga4275592018-08-31 10:52:47 -040096
97 String fieldType = FieldType(context, type, layout);
98 bool isPrimitive = primitiveTypes.find(fieldType) != primitiveTypes.end();
99 if (isPrimitive) {
100 return fieldType;
101 } else {
102 return String::printf("const %s&", fieldType.c_str());
103 }
104}
105
Ethan Nicholas762466e2017-06-29 10:03:38 -0400106void HCodeGenerator::writef(const char* s, va_list va) {
107 static constexpr int BUFFER_SIZE = 1024;
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400108 va_list copy;
109 va_copy(copy, va);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400110 char buffer[BUFFER_SIZE];
111 int length = vsnprintf(buffer, BUFFER_SIZE, s, va);
112 if (length < BUFFER_SIZE) {
113 fOut->write(buffer, length);
114 } else {
115 std::unique_ptr<char[]> heap(new char[length + 1]);
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400116 vsprintf(heap.get(), s, copy);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400117 fOut->write(heap.get(), length);
118 }
Greg Kaiser27f83022019-02-11 08:32:13 -0800119 va_end(copy);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400120}
121
122void HCodeGenerator::writef(const char* s, ...) {
123 va_list va;
124 va_start(va, s);
125 this->writef(s, va);
126 va_end(va);
127}
128
129bool HCodeGenerator::writeSection(const char* name, const char* prefix) {
Ethan Nicholas68990be2017-07-13 09:36:52 -0400130 const Section* s = fSectionAndParameterHelper.getSection(name);
131 if (s) {
132 this->writef("%s%s", prefix, s->fText.c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400133 return true;
134 }
135 return false;
136}
137
138void HCodeGenerator::writeExtraConstructorParams(const char* separator) {
139 // super-simple parse, just assume the last token before a comma is the name of a parameter
140 // (which is true as long as there are no multi-parameter template types involved). Will replace
141 // this with something more robust if the need arises.
John Stiles02b11282020-08-10 15:25:24 -0400142 const Section* section = fSectionAndParameterHelper.getSection(kConstructorParamsSection);
Ethan Nicholas68990be2017-07-13 09:36:52 -0400143 if (section) {
144 const char* s = section->fText.c_str();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400145 #define BUFFER_SIZE 64
146 char lastIdentifier[BUFFER_SIZE];
147 int lastIdentifierLength = 0;
148 bool foundBreak = false;
149 while (*s) {
150 char c = *s;
151 ++s;
152 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
153 c == '_') {
154 if (foundBreak) {
155 lastIdentifierLength = 0;
156 foundBreak = false;
157 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400158 SkASSERT(lastIdentifierLength < BUFFER_SIZE);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400159 lastIdentifier[lastIdentifierLength] = c;
160 ++lastIdentifierLength;
161 } else {
162 foundBreak = true;
163 if (c == ',') {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400164 SkASSERT(lastIdentifierLength < BUFFER_SIZE);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400165 lastIdentifier[lastIdentifierLength] = 0;
166 this->writef("%s%s", separator, lastIdentifier);
167 separator = ", ";
168 } else if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
169 lastIdentifierLength = 0;
170 }
171 }
172 }
173 if (lastIdentifierLength) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400174 SkASSERT(lastIdentifierLength < BUFFER_SIZE);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400175 lastIdentifier[lastIdentifierLength] = 0;
176 this->writef("%s%s", separator, lastIdentifier);
177 }
178 }
179}
180
181void HCodeGenerator::writeMake() {
182 const char* separator;
John Stiles02b11282020-08-10 15:25:24 -0400183 if (!this->writeSection(kMakeSection)) {
Brian Salomonaff329b2017-08-11 09:40:37 -0400184 this->writef(" static std::unique_ptr<GrFragmentProcessor> Make(");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400185 separator = "";
Ethan Nicholas68990be2017-07-13 09:36:52 -0400186 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholasd608c092017-10-26 09:30:08 -0400187 this->writef("%s%s %s", separator, ParameterType(fContext, param->fType,
188 param->fModifiers.fLayout).c_str(),
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700189 String(param->fName).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400190 separator = ", ";
191 }
John Stiles02b11282020-08-10 15:25:24 -0400192 this->writeSection(kConstructorParamsSection, separator);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400193 this->writef(") {\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400194 " return std::unique_ptr<GrFragmentProcessor>(new %s(",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400195 fFullName.c_str());
196 separator = "";
Ethan Nicholas68990be2017-07-13 09:36:52 -0400197 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Greg Daniel43956122020-02-11 15:49:27 -0500198 if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type ||
199 param->fType.nonnullable().kind() == Type::kSampler_Kind) {
Robert Phillips7a59f232017-11-08 15:31:30 -0500200 this->writef("%sstd::move(%s)", separator, String(param->fName).c_str());
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400201 } else {
202 this->writef("%s%s", separator, String(param->fName).c_str());
203 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400204 separator = ", ";
205 }
206 this->writeExtraConstructorParams(separator);
207 this->writef("));\n"
208 " }\n");
209 }
210}
211
Ethan Nicholas68990be2017-07-13 09:36:52 -0400212void HCodeGenerator::failOnSection(const char* section, const char* msg) {
213 std::vector<const Section*> s = fSectionAndParameterHelper.getSections(section);
214 if (s.size()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700215 fErrors.error(s[0]->fOffset, String("@") + section + " " + msg);
Ethan Nicholas68990be2017-07-13 09:36:52 -0400216 }
217}
218
Ethan Nicholas762466e2017-06-29 10:03:38 -0400219void HCodeGenerator::writeConstructor() {
John Stiles02b11282020-08-10 15:25:24 -0400220 if (this->writeSection(kConstructorSection)) {
Ethan Nicholas68990be2017-07-13 09:36:52 -0400221 const char* msg = "may not be present when constructor is overridden";
John Stiles02b11282020-08-10 15:25:24 -0400222 this->failOnSection(kConstructorCodeSection, msg);
223 this->failOnSection(kConstructorParamsSection, msg);
224 this->failOnSection(kInitializersSection, msg);
225 this->failOnSection(kOptimizationFlagsSection, msg);
Robert Phillips1e8501e2018-03-23 15:00:20 -0400226 return;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400227 }
228 this->writef(" %s(", fFullName.c_str());
229 const char* separator = "";
Ethan Nicholas68990be2017-07-13 09:36:52 -0400230 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholasd608c092017-10-26 09:30:08 -0400231 this->writef("%s%s %s", separator, ParameterType(fContext, param->fType,
232 param->fModifiers.fLayout).c_str(),
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700233 String(param->fName).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400234 separator = ", ";
235 }
John Stiles02b11282020-08-10 15:25:24 -0400236 this->writeSection(kConstructorParamsSection, separator);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400237 this->writef(")\n"
Ethan Nicholasabff9562017-10-09 10:54:08 -0400238 " : INHERITED(k%s_ClassID", fFullName.c_str());
John Stiles02b11282020-08-10 15:25:24 -0400239 if (!this->writeSection(kOptimizationFlagsSection, ", (OptimizationFlags) ")) {
Ethan Nicholasabff9562017-10-09 10:54:08 -0400240 this->writef(", kNone_OptimizationFlags");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400241 }
242 this->writef(")");
John Stiles02b11282020-08-10 15:25:24 -0400243 this->writeSection(kInitializersSection, "\n , ");
Ethan Nicholas68990be2017-07-13 09:36:52 -0400244 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700245 String nameString(param->fName);
246 const char* name = nameString.c_str();
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500247 const Type& type = param->fType.nonnullable();
248 if (type.kind() == Type::kSampler_Kind) {
Ethan Nicholas68990be2017-07-13 09:36:52 -0400249 this->writef("\n , %s(std::move(%s)", FieldName(name).c_str(), name);
250 for (const Section* s : fSectionAndParameterHelper.getSections(
John Stiles02b11282020-08-10 15:25:24 -0400251 kSamplerParamsSection)) {
Ethan Nicholas68990be2017-07-13 09:36:52 -0400252 if (s->fArgument == name) {
253 this->writef(", %s", s->fText.c_str());
254 }
255 }
256 this->writef(")");
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500257 } else if (type == *fContext.fFragmentProcessor_Type) {
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400258 // do nothing
Ethan Nicholas762466e2017-06-29 10:03:38 -0400259 } else {
260 this->writef("\n , %s(%s)", FieldName(name).c_str(), name);
261 }
262 }
263 this->writef(" {\n");
John Stiles02b11282020-08-10 15:25:24 -0400264 this->writeSection(kConstructorCodeSection);
Michael Ludwige88320b2020-06-24 09:04:56 -0400265
Michael Ludwig8f3a8362020-06-29 17:27:00 -0400266 if (Analysis::ReferencesSampleCoords(fProgram)) {
Michael Ludwige88320b2020-06-24 09:04:56 -0400267 this->writef(" this->setUsesSampleCoordsDirectly();\n");
268 }
269
Brian Salomonf7dcd762018-07-30 14:48:15 -0400270 int samplerCount = 0;
John Stiles88183902020-06-10 16:40:38 -0400271 for (const Variable* param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400272 if (param->fType.kind() == Type::kSampler_Kind) {
Brian Salomonf7dcd762018-07-30 14:48:15 -0400273 ++samplerCount;
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500274 } else if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
Brian Osman54867de2020-07-10 14:22:57 -0400275 if (param->fType.kind() != Type::kNullable_Kind) {
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500276 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 Osman12c5d292020-07-13 16:11:35 -0400293 this->writef(" this->registerChild(std::move(%s), %s);",
Michael Ludwig9aba6252020-06-22 14:46:36 -0400294 String(param->fName).c_str(),
Brian Osman1298bc42020-06-30 13:39:35 -0400295 usageArg.c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400296 }
297 }
Brian Salomonf7dcd762018-07-30 14:48:15 -0400298 if (samplerCount) {
299 this->writef(" this->setTextureSamplerCnt(%d);", samplerCount);
300 }
Ethan Nicholasabff9562017-10-09 10:54:08 -0400301 this->writef(" }\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400302}
303
304void HCodeGenerator::writeFields() {
John Stiles02b11282020-08-10 15:25:24 -0400305 this->writeSection(kFieldsSection);
Ethan Nicholas68990be2017-07-13 09:36:52 -0400306 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500307 String name = FieldName(String(param->fName).c_str());
308 if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
Brian Osman12c5d292020-07-13 16:11:35 -0400309 // Don't need to write any fields, FPs are held as children
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500310 } else {
311 this->writef(" %s %s;\n", FieldType(fContext, param->fType,
312 param->fModifiers.fLayout).c_str(),
313 name.c_str());
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400314 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400315 }
316}
317
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500318String HCodeGenerator::GetHeader(const Program& program, ErrorReporter& errors) {
319 SymbolTable types(&errors);
320 Parser parser(program.fSource->c_str(), program.fSource->length(), types, errors);
321 for (;;) {
322 Token header = parser.nextRawToken();
323 switch (header.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400324 case Token::Kind::TK_WHITESPACE:
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500325 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400326 case Token::Kind::TK_BLOCK_COMMENT:
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500327 return String(program.fSource->c_str() + header.fOffset, header.fLength);
328 default:
329 return "";
330 }
331 }
332}
333
Ethan Nicholas762466e2017-06-29 10:03:38 -0400334bool HCodeGenerator::generateCode() {
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500335 this->writef("%s\n", GetHeader(fProgram, fErrors).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400336 this->writef(kFragmentProcessorHeader, fFullName.c_str());
337 this->writef("#ifndef %s_DEFINED\n"
John Stiles88183902020-06-10 16:40:38 -0400338 "#define %s_DEFINED\n"
John Stiles776c2842020-08-13 09:16:49 -0400339 "\n"
340 "#include \"include/core/SkM44.h\"\n"
341 "#include \"include/core/SkTypes.h\"\n"
John Stiles88183902020-06-10 16:40:38 -0400342 "\n",
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400343 fFullName.c_str(),
344 fFullName.c_str());
John Stiles02b11282020-08-10 15:25:24 -0400345 this->writeSection(kHeaderSection);
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500346 this->writef("\n"
John Stiles88183902020-06-10 16:40:38 -0400347 "#include \"src/gpu/GrFragmentProcessor.h\"\n"
John Stiles776c2842020-08-13 09:16:49 -0400348 "\n"
349 "class %s : public GrFragmentProcessor {\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400350 "public:\n",
351 fFullName.c_str());
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400352 for (const auto& p : fProgram) {
353 if (ProgramElement::kEnum_Kind == p.fKind && !((Enum&) p).fBuiltin) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -0500354 this->writef("%s\n", ((Enum&) p).code().c_str());
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500355 }
356 }
John Stiles02b11282020-08-10 15:25:24 -0400357 this->writeSection(kClassSection);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400358 this->writeMake();
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400359 this->writef(" %s(const %s& src);\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400360 " std::unique_ptr<GrFragmentProcessor> clone() const override;\n"
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400361 " const char* name() const override { return \"%s\"; }\n",
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400362 fFullName.c_str(), fFullName.c_str(), fName.c_str());
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400363 this->writeFields();
364 this->writef("private:\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400365 this->writeConstructor();
366 this->writef(" GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n"
John Stiles776c2842020-08-13 09:16:49 -0400367 " void onGetGLSLProcessorKey(const GrShaderCaps&, "
Ethan Nicholas762466e2017-06-29 10:03:38 -0400368 "GrProcessorKeyBuilder*) const override;\n"
Brian Salomonf7dcd762018-07-30 14:48:15 -0400369 " bool onIsEqual(const GrFragmentProcessor&) const override;\n");
370 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
371 if (param->fType.kind() == Type::kSampler_Kind) {
372 this->writef(" const TextureSampler& onTextureSampler(int) const override;");
373 break;
374 }
375 }
John Stiles776c2842020-08-13 09:16:49 -0400376 this->writef("#if GR_TEST_UTILS\n"
377 " SkString onDumpInfo() const override;\n"
378 "#endif\n"
379 " GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n"
380 " typedef GrFragmentProcessor INHERITED;\n"
381 "};\n");
John Stiles02b11282020-08-10 15:25:24 -0400382 this->writeSection(kHeaderEndSection);
Greg Daniel3e8c3452018-04-06 10:37:55 -0400383 this->writef("#endif\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400384 return 0 == fErrors.errorCount();
385}
386
John Stilesa6841be2020-08-06 14:11:56 -0400387} // namespace SkSL
Ethan Nicholas2a479a52020-08-18 16:29:45 -0400388
389#endif // defined(SKSL_STANDALONE) || defined(GR_TEST_UTILS)