blob: f53b5726b94d32e4c9f896e3d9f8a6d825b322ba [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"
Brian Osman5ee90ff2020-06-10 16:08:54 -040011#include "src/sksl/SkSLSampleMatrix.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/sksl/SkSLUtil.h"
13#include "src/sksl/ir/SkSLEnum.h"
14#include "src/sksl/ir/SkSLFunctionDeclaration.h"
15#include "src/sksl/ir/SkSLFunctionDefinition.h"
16#include "src/sksl/ir/SkSLSection.h"
17#include "src/sksl/ir/SkSLVarDeclarations.h"
Ethan Nicholas762466e2017-06-29 10:03:38 -040018
Michael Ludwiga4275592018-08-31 10:52:47 -040019#include <set>
20
Ethan Nicholas762466e2017-06-29 10:03:38 -040021namespace SkSL {
22
Ethan Nicholasc9472af2017-10-10 16:30:21 -040023HCodeGenerator::HCodeGenerator(const Context* context, const Program* program,
24 ErrorReporter* errors, String name, OutputStream* out)
Ethan Nicholas762466e2017-06-29 10:03:38 -040025: INHERITED(program, errors, out)
Ethan Nicholasc9472af2017-10-10 16:30:21 -040026, fContext(*context)
Ethan Nicholas762466e2017-06-29 10:03:38 -040027, fName(std::move(name))
28, fFullName(String::printf("Gr%s", fName.c_str()))
Ethan Nicholasd4efe682019-08-29 16:10:13 -040029, fSectionAndParameterHelper(program, *errors) {}
Ethan Nicholas762466e2017-06-29 10:03:38 -040030
Ethan Nicholasd608c092017-10-26 09:30:08 -040031String HCodeGenerator::ParameterType(const Context& context, const Type& type,
32 const Layout& layout) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040033 Layout::CType ctype = ParameterCType(context, type, layout);
34 if (ctype != Layout::CType::kDefault) {
35 return Layout::CTypeToStr(ctype);
36 }
37 return type.name();
38}
39
40Layout::CType HCodeGenerator::ParameterCType(const Context& context, const Type& type,
41 const Layout& layout) {
42 if (layout.fCType != Layout::CType::kDefault) {
Ethan Nicholasd608c092017-10-26 09:30:08 -040043 return layout.fCType;
Ethan Nicholas78aceb22018-08-31 16:13:58 -040044 }
Ethan Nicholasee1c8a72019-02-22 10:50:47 -050045 if (type.kind() == Type::kNullable_Kind) {
46 return ParameterCType(context, type.componentType(), layout);
47 } else if (type == *context.fFloat_Type || type == *context.fHalf_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040048 return Layout::CType::kFloat;
Michael Ludwiga4275592018-08-31 10:52:47 -040049 } else if (type == *context.fInt_Type ||
50 type == *context.fShort_Type ||
51 type == *context.fByte_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040052 return Layout::CType::kInt32;
Ethan Nicholasc9472af2017-10-10 16:30:21 -040053 } else if (type == *context.fFloat2_Type || type == *context.fHalf2_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040054 return Layout::CType::kSkPoint;
Michael Ludwiga4275592018-08-31 10:52:47 -040055 } else if (type == *context.fInt2_Type ||
56 type == *context.fShort2_Type ||
57 type == *context.fByte2_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040058 return Layout::CType::kSkIPoint;
Ruiqi Maob609e6d2018-07-17 10:19:38 -040059 } else if (type == *context.fInt4_Type ||
60 type == *context.fShort4_Type ||
61 type == *context.fByte4_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040062 return Layout::CType::kSkIRect;
Ethan Nicholasc9472af2017-10-10 16:30:21 -040063 } else if (type == *context.fFloat4_Type || type == *context.fHalf4_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040064 return Layout::CType::kSkRect;
Michael Ludwiga4275592018-08-31 10:52:47 -040065 } else if (type == *context.fFloat3x3_Type || type == *context.fHalf3x3_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040066 return Layout::CType::kSkMatrix;
Ethan Nicholasc9472af2017-10-10 16:30:21 -040067 } else if (type == *context.fFloat4x4_Type || type == *context.fHalf4x4_Type) {
Mike Reedb26b4e72020-01-22 14:31:21 -050068 return Layout::CType::kSkM44;
Ethan Nicholas762466e2017-06-29 10:03:38 -040069 } else if (type.kind() == Type::kSampler_Kind) {
Greg Daniel43956122020-02-11 15:49:27 -050070 return Layout::CType::kGrSurfaceProxyView;
Ethan Nicholasc9472af2017-10-10 16:30:21 -040071 } else if (type == *context.fFragmentProcessor_Type) {
Ethan Nicholas78aceb22018-08-31 16:13:58 -040072 return Layout::CType::kGrFragmentProcessor;
Ethan Nicholas762466e2017-06-29 10:03:38 -040073 }
Ethan Nicholas78aceb22018-08-31 16:13:58 -040074 return Layout::CType::kDefault;
Ethan Nicholas762466e2017-06-29 10:03:38 -040075}
76
Ethan Nicholasd608c092017-10-26 09:30:08 -040077String HCodeGenerator::FieldType(const Context& context, const Type& type,
78 const Layout& layout) {
Ethan Nicholas762466e2017-06-29 10:03:38 -040079 if (type.kind() == Type::kSampler_Kind) {
80 return "TextureSampler";
Ethan Nicholasc9472af2017-10-10 16:30:21 -040081 } else if (type == *context.fFragmentProcessor_Type) {
82 // we don't store fragment processors in fields, they get registered via
83 // registerChildProcessor instead
Ethan Nicholasd9d33c32018-06-12 11:05:59 -040084 SkASSERT(false);
Ethan Nicholasc9472af2017-10-10 16:30:21 -040085 return "<error>";
Ethan Nicholas762466e2017-06-29 10:03:38 -040086 }
Ethan Nicholasd608c092017-10-26 09:30:08 -040087 return ParameterType(context, type, layout);
Ethan Nicholas762466e2017-06-29 10:03:38 -040088}
89
Michael Ludwiga4275592018-08-31 10:52:47 -040090String HCodeGenerator::AccessType(const Context& context, const Type& type,
91 const Layout& layout) {
Michael Ludwig72efd802018-08-31 13:26:19 -040092 static const std::set<String> primitiveTypes = { "int32_t", "float", "bool", "SkPMColor" };
Michael Ludwiga4275592018-08-31 10:52:47 -040093
94 String fieldType = FieldType(context, type, layout);
95 bool isPrimitive = primitiveTypes.find(fieldType) != primitiveTypes.end();
96 if (isPrimitive) {
97 return fieldType;
98 } else {
99 return String::printf("const %s&", fieldType.c_str());
100 }
101}
102
Ethan Nicholas762466e2017-06-29 10:03:38 -0400103void HCodeGenerator::writef(const char* s, va_list va) {
104 static constexpr int BUFFER_SIZE = 1024;
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400105 va_list copy;
106 va_copy(copy, va);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400107 char buffer[BUFFER_SIZE];
108 int length = vsnprintf(buffer, BUFFER_SIZE, s, va);
109 if (length < BUFFER_SIZE) {
110 fOut->write(buffer, length);
111 } else {
112 std::unique_ptr<char[]> heap(new char[length + 1]);
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400113 vsprintf(heap.get(), s, copy);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400114 fOut->write(heap.get(), length);
115 }
Greg Kaiser27f83022019-02-11 08:32:13 -0800116 va_end(copy);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400117}
118
119void HCodeGenerator::writef(const char* s, ...) {
120 va_list va;
121 va_start(va, s);
122 this->writef(s, va);
123 va_end(va);
124}
125
126bool HCodeGenerator::writeSection(const char* name, const char* prefix) {
Ethan Nicholas68990be2017-07-13 09:36:52 -0400127 const Section* s = fSectionAndParameterHelper.getSection(name);
128 if (s) {
129 this->writef("%s%s", prefix, s->fText.c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400130 return true;
131 }
132 return false;
133}
134
135void HCodeGenerator::writeExtraConstructorParams(const char* separator) {
136 // super-simple parse, just assume the last token before a comma is the name of a parameter
137 // (which is true as long as there are no multi-parameter template types involved). Will replace
138 // this with something more robust if the need arises.
Ethan Nicholas68990be2017-07-13 09:36:52 -0400139 const Section* section = fSectionAndParameterHelper.getSection(CONSTRUCTOR_PARAMS_SECTION);
140 if (section) {
141 const char* s = section->fText.c_str();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400142 #define BUFFER_SIZE 64
143 char lastIdentifier[BUFFER_SIZE];
144 int lastIdentifierLength = 0;
145 bool foundBreak = false;
146 while (*s) {
147 char c = *s;
148 ++s;
149 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
150 c == '_') {
151 if (foundBreak) {
152 lastIdentifierLength = 0;
153 foundBreak = false;
154 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400155 SkASSERT(lastIdentifierLength < BUFFER_SIZE);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400156 lastIdentifier[lastIdentifierLength] = c;
157 ++lastIdentifierLength;
158 } else {
159 foundBreak = true;
160 if (c == ',') {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400161 SkASSERT(lastIdentifierLength < BUFFER_SIZE);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400162 lastIdentifier[lastIdentifierLength] = 0;
163 this->writef("%s%s", separator, lastIdentifier);
164 separator = ", ";
165 } else if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
166 lastIdentifierLength = 0;
167 }
168 }
169 }
170 if (lastIdentifierLength) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400171 SkASSERT(lastIdentifierLength < BUFFER_SIZE);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400172 lastIdentifier[lastIdentifierLength] = 0;
173 this->writef("%s%s", separator, lastIdentifier);
174 }
175 }
176}
177
178void HCodeGenerator::writeMake() {
179 const char* separator;
180 if (!this->writeSection(MAKE_SECTION)) {
Brian Salomonaff329b2017-08-11 09:40:37 -0400181 this->writef(" static std::unique_ptr<GrFragmentProcessor> Make(");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400182 separator = "";
Ethan Nicholas68990be2017-07-13 09:36:52 -0400183 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholasd608c092017-10-26 09:30:08 -0400184 this->writef("%s%s %s", separator, ParameterType(fContext, param->fType,
185 param->fModifiers.fLayout).c_str(),
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700186 String(param->fName).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400187 separator = ", ";
188 }
189 this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator);
190 this->writef(") {\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400191 " return std::unique_ptr<GrFragmentProcessor>(new %s(",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400192 fFullName.c_str());
193 separator = "";
Ethan Nicholas68990be2017-07-13 09:36:52 -0400194 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Greg Daniel43956122020-02-11 15:49:27 -0500195 if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type ||
196 param->fType.nonnullable().kind() == Type::kSampler_Kind) {
Robert Phillips7a59f232017-11-08 15:31:30 -0500197 this->writef("%sstd::move(%s)", separator, String(param->fName).c_str());
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400198 } else {
199 this->writef("%s%s", separator, String(param->fName).c_str());
200 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400201 separator = ", ";
202 }
203 this->writeExtraConstructorParams(separator);
204 this->writef("));\n"
205 " }\n");
206 }
207}
208
Ethan Nicholas68990be2017-07-13 09:36:52 -0400209void HCodeGenerator::failOnSection(const char* section, const char* msg) {
210 std::vector<const Section*> s = fSectionAndParameterHelper.getSections(section);
211 if (s.size()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700212 fErrors.error(s[0]->fOffset, String("@") + section + " " + msg);
Ethan Nicholas68990be2017-07-13 09:36:52 -0400213 }
214}
215
Ethan Nicholas762466e2017-06-29 10:03:38 -0400216void HCodeGenerator::writeConstructor() {
217 if (this->writeSection(CONSTRUCTOR_SECTION)) {
Ethan Nicholas68990be2017-07-13 09:36:52 -0400218 const char* msg = "may not be present when constructor is overridden";
219 this->failOnSection(CONSTRUCTOR_CODE_SECTION, msg);
220 this->failOnSection(CONSTRUCTOR_PARAMS_SECTION, msg);
Ethan Nicholas68990be2017-07-13 09:36:52 -0400221 this->failOnSection(INITIALIZERS_SECTION, msg);
222 this->failOnSection(OPTIMIZATION_FLAGS_SECTION, msg);
Robert Phillips1e8501e2018-03-23 15:00:20 -0400223 return;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400224 }
225 this->writef(" %s(", fFullName.c_str());
226 const char* separator = "";
Ethan Nicholas68990be2017-07-13 09:36:52 -0400227 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholasd608c092017-10-26 09:30:08 -0400228 this->writef("%s%s %s", separator, ParameterType(fContext, param->fType,
229 param->fModifiers.fLayout).c_str(),
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700230 String(param->fName).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400231 separator = ", ";
232 }
233 this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator);
234 this->writef(")\n"
Ethan Nicholasabff9562017-10-09 10:54:08 -0400235 " : INHERITED(k%s_ClassID", fFullName.c_str());
236 if (!this->writeSection(OPTIMIZATION_FLAGS_SECTION, ", (OptimizationFlags) ")) {
237 this->writef(", kNone_OptimizationFlags");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400238 }
239 this->writef(")");
240 this->writeSection(INITIALIZERS_SECTION, "\n , ");
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400241 const auto transforms = fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION);
242 for (size_t i = 0; i < transforms.size(); ++i) {
243 const Section& s = *transforms[i];
244 String field = CoordTransformName(s.fArgument.c_str(), i);
245 if (s.fArgument.size()) {
Greg Daniel67da6652020-02-12 14:09:34 -0500246 this->writef("\n , %s(%s, %s.proxy(), %s.origin())", field.c_str(), s.fText.c_str(),
247 FieldName(s.fArgument.c_str()).c_str(),
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400248 FieldName(s.fArgument.c_str()).c_str());
249 }
250 else {
251 this->writef("\n , %s(%s)", field.c_str(), s.fText.c_str());
252 }
253 }
Ethan Nicholas68990be2017-07-13 09:36:52 -0400254 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700255 String nameString(param->fName);
256 const char* name = nameString.c_str();
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500257 const Type& type = param->fType.nonnullable();
258 if (type.kind() == Type::kSampler_Kind) {
Ethan Nicholas68990be2017-07-13 09:36:52 -0400259 this->writef("\n , %s(std::move(%s)", FieldName(name).c_str(), name);
260 for (const Section* s : fSectionAndParameterHelper.getSections(
261 SAMPLER_PARAMS_SECTION)) {
262 if (s->fArgument == name) {
263 this->writef(", %s", s->fText.c_str());
264 }
265 }
266 this->writef(")");
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500267 } else if (type == *fContext.fFragmentProcessor_Type) {
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400268 // do nothing
Ethan Nicholas762466e2017-06-29 10:03:38 -0400269 } else {
270 this->writef("\n , %s(%s)", FieldName(name).c_str(), name);
271 }
272 }
273 this->writef(" {\n");
274 this->writeSection(CONSTRUCTOR_CODE_SECTION);
Brian Salomonf7dcd762018-07-30 14:48:15 -0400275 int samplerCount = 0;
John Stiles88183902020-06-10 16:40:38 -0400276 for (const Variable* param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400277 if (param->fType.kind() == Type::kSampler_Kind) {
Brian Salomonf7dcd762018-07-30 14:48:15 -0400278 ++samplerCount;
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500279 } else if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
280 if (param->fType.kind() == Type::kNullable_Kind) {
281 this->writef(" if (%s) {\n", String(param->fName).c_str());
282 } else {
283 this->writef(" SkASSERT(%s);", String(param->fName).c_str());
284 }
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400285 if (fSectionAndParameterHelper.hasCoordOverrides(*param)) {
Ethan Nicholas58430122020-04-14 09:54:02 -0400286 this->writef(" %s->setSampledWithExplicitCoords();",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400287 String(param->fName).c_str());
288 }
Brian Osman5ee90ff2020-06-10 16:08:54 -0400289 SampleMatrix matrix = SampleMatrix::Make(fProgram, *param);
Ethan Nicholasafe2c902020-04-28 13:55:02 -0400290 switch (matrix.fKind) {
291 case SampleMatrix::Kind::kVariable:
Ethan Nicholaseee14b82020-05-26 12:51:12 -0400292 this->writef(" %s->setSampleMatrix(SkSL::SampleMatrix("
293 "SkSL::SampleMatrix::Kind::kVariable));",
Ethan Nicholasafe2c902020-04-28 13:55:02 -0400294 String(param->fName).c_str());
295 break;
296 case SampleMatrix::Kind::kConstantOrUniform:
297 this->writef(" %s->setSampleMatrix(SkSL::SampleMatrix("
298 "SkSL::SampleMatrix::Kind::kConstantOrUniform, this, \"%s\"));",
299 String(param->fName).c_str(),
300 matrix.fExpression.c_str());
301 break;
302 case SampleMatrix::Kind::kMixed:
303 this->writef(" %s->setSampleMatrix(SkSL::SampleMatrix("
304 "SkSL::SampleMatrix::Kind::kMixed, this, \"%s\"));",
305 String(param->fName).c_str(),
306 matrix.fExpression.c_str());
307 break;
308 case SampleMatrix::Kind::kNone:
309 break;
310 }
John Stiles88183902020-06-10 16:40:38 -0400311 this->writef(" %s_index = this->registerChildProcessor(std::move(%s));",
312 FieldName(String(param->fName).c_str()).c_str(),
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400313 String(param->fName).c_str());
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500314 if (param->fType.kind() == Type::kNullable_Kind) {
315 this->writef(" }");
316 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400317 }
318 }
Brian Salomonf7dcd762018-07-30 14:48:15 -0400319 if (samplerCount) {
320 this->writef(" this->setTextureSamplerCnt(%d);", samplerCount);
321 }
Ethan Nicholas929a6812018-08-06 14:56:59 -0400322 for (size_t i = 0; i < transforms.size(); ++i) {
323 const Section& s = *transforms[i];
324 String field = CoordTransformName(s.fArgument.c_str(), i);
325 this->writef(" this->addCoordTransform(&%s);\n", field.c_str());
Ethan Nicholas68990be2017-07-13 09:36:52 -0400326 }
Ethan Nicholasabff9562017-10-09 10:54:08 -0400327 this->writef(" }\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400328}
329
330void HCodeGenerator::writeFields() {
331 this->writeSection(FIELDS_SECTION);
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400332 const auto transforms = fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION);
333 for (size_t i = 0; i < transforms.size(); ++i) {
334 const Section& s = *transforms[i];
335 this->writef(" GrCoordTransform %s;\n",
336 CoordTransformName(s.fArgument.c_str(), i).c_str());
337 }
Ethan Nicholas68990be2017-07-13 09:36:52 -0400338 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholasee1c8a72019-02-22 10:50:47 -0500339 String name = FieldName(String(param->fName).c_str());
340 if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
341 this->writef(" int %s_index = -1;\n", name.c_str());
342 } else {
343 this->writef(" %s %s;\n", FieldType(fContext, param->fType,
344 param->fModifiers.fLayout).c_str(),
345 name.c_str());
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400346 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400347 }
348}
349
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500350String HCodeGenerator::GetHeader(const Program& program, ErrorReporter& errors) {
351 SymbolTable types(&errors);
352 Parser parser(program.fSource->c_str(), program.fSource->length(), types, errors);
353 for (;;) {
354 Token header = parser.nextRawToken();
355 switch (header.fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400356 case Token::Kind::TK_WHITESPACE:
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500357 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400358 case Token::Kind::TK_BLOCK_COMMENT:
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500359 return String(program.fSource->c_str() + header.fOffset, header.fLength);
360 default:
361 return "";
362 }
363 }
364}
365
Ethan Nicholas762466e2017-06-29 10:03:38 -0400366bool HCodeGenerator::generateCode() {
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500367 this->writef("%s\n", GetHeader(fProgram, fErrors).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400368 this->writef(kFragmentProcessorHeader, fFullName.c_str());
369 this->writef("#ifndef %s_DEFINED\n"
John Stiles88183902020-06-10 16:40:38 -0400370 "#define %s_DEFINED\n"
371 "\n",
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400372 fFullName.c_str(),
373 fFullName.c_str());
John Stiles88183902020-06-10 16:40:38 -0400374 this->writef("#include \"include/core/SkM44.h\"\n"
375 "#include \"include/core/SkTypes.h\"\n"
376 "\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400377 this->writeSection(HEADER_SECTION);
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500378 this->writef("\n"
379 "#include \"src/gpu/GrCoordTransform.h\"\n"
John Stiles88183902020-06-10 16:40:38 -0400380 "#include \"src/gpu/GrFragmentProcessor.h\"\n"
381 "\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400382 this->writef("class %s : public GrFragmentProcessor {\n"
383 "public:\n",
384 fFullName.c_str());
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400385 for (const auto& p : fProgram) {
386 if (ProgramElement::kEnum_Kind == p.fKind && !((Enum&) p).fBuiltin) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -0500387 this->writef("%s\n", ((Enum&) p).code().c_str());
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500388 }
389 }
Ethan Nicholase9d172a2017-11-20 12:12:24 -0500390 this->writeSection(CLASS_SECTION);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400391 this->writeMake();
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400392 this->writef(" %s(const %s& src);\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400393 " std::unique_ptr<GrFragmentProcessor> clone() const override;\n"
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400394 " const char* name() const override { return \"%s\"; }\n",
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400395 fFullName.c_str(), fFullName.c_str(), fName.c_str());
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400396 this->writeFields();
397 this->writef("private:\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400398 this->writeConstructor();
399 this->writef(" GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n"
400 " void onGetGLSLProcessorKey(const GrShaderCaps&,"
401 "GrProcessorKeyBuilder*) const override;\n"
Brian Salomonf7dcd762018-07-30 14:48:15 -0400402 " bool onIsEqual(const GrFragmentProcessor&) const override;\n");
403 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
404 if (param->fType.kind() == Type::kSampler_Kind) {
405 this->writef(" const TextureSampler& onTextureSampler(int) const override;");
406 break;
407 }
408 }
409 this->writef(" GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400410 this->writef(" typedef GrFragmentProcessor INHERITED;\n"
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400411 "};\n");
412 this->writeSection(HEADER_END_SECTION);
Greg Daniel3e8c3452018-04-06 10:37:55 -0400413 this->writef("#endif\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400414 return 0 == fErrors.errorCount();
415}
416
417} // namespace