blob: 4eab6bae6bf29fa452c28149775951916625f87d [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
8#include "SkSLCPPCodeGenerator.h"
9
10#include "SkSLCompiler.h"
11#include "SkSLHCodeGenerator.h"
12
13namespace SkSL {
14
15static bool needs_uniform_var(const Variable& var) {
Ethan Nicholas5f9836e2017-12-20 15:16:33 -050016 return (var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
17 var.fType.kind() != Type::kSampler_Kind;
Ethan Nicholas762466e2017-06-29 10:03:38 -040018}
19
20CPPCodeGenerator::CPPCodeGenerator(const Context* context, const Program* program,
21 ErrorReporter* errors, String name, OutputStream* out)
22: INHERITED(context, program, errors, out)
23, fName(std::move(name))
24, fFullName(String::printf("Gr%s", fName.c_str()))
25, fSectionAndParameterHelper(*program, *errors) {
26 fLineEnding = "\\n";
27}
28
29void CPPCodeGenerator::writef(const char* s, va_list va) {
30 static constexpr int BUFFER_SIZE = 1024;
Ethan Nicholas9fb036f2017-07-05 16:19:09 -040031 va_list copy;
32 va_copy(copy, va);
Ethan Nicholas762466e2017-06-29 10:03:38 -040033 char buffer[BUFFER_SIZE];
34 int length = vsnprintf(buffer, BUFFER_SIZE, s, va);
35 if (length < BUFFER_SIZE) {
36 fOut->write(buffer, length);
37 } else {
38 std::unique_ptr<char[]> heap(new char[length + 1]);
Ethan Nicholas9fb036f2017-07-05 16:19:09 -040039 vsprintf(heap.get(), s, copy);
Ethan Nicholas762466e2017-06-29 10:03:38 -040040 fOut->write(heap.get(), length);
41 }
z102.zhangd74f2c82018-08-10 09:08:47 +080042 va_end(copy);
Ethan Nicholas762466e2017-06-29 10:03:38 -040043}
44
45void CPPCodeGenerator::writef(const char* s, ...) {
46 va_list va;
47 va_start(va, s);
48 this->writef(s, va);
49 va_end(va);
50}
51
52void CPPCodeGenerator::writeHeader() {
53}
54
Ethan Nicholasf7b88202017-09-18 14:10:39 -040055bool CPPCodeGenerator::usesPrecisionModifiers() const {
56 return false;
Ethan Nicholas762466e2017-06-29 10:03:38 -040057}
58
Ethan Nicholasf7b88202017-09-18 14:10:39 -040059String CPPCodeGenerator::getTypeName(const Type& type) {
60 return type.name();
Ethan Nicholas5af9ea32017-07-28 15:19:46 -040061}
Ethan Nicholasf7b88202017-09-18 14:10:39 -040062
Ethan Nicholas762466e2017-06-29 10:03:38 -040063void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
64 Precedence parentPrecedence) {
65 if (b.fOperator == Token::PERCENT) {
66 // need to use "%%" instead of "%" b/c the code will be inside of a printf
67 Precedence precedence = GetBinaryPrecedence(b.fOperator);
68 if (precedence >= parentPrecedence) {
69 this->write("(");
70 }
71 this->writeExpression(*b.fLeft, precedence);
72 this->write(" %% ");
73 this->writeExpression(*b.fRight, precedence);
74 if (precedence >= parentPrecedence) {
75 this->write(")");
76 }
77 } else {
78 INHERITED::writeBinaryExpression(b, parentPrecedence);
79 }
80}
81
82void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) {
83 const Expression& base = *i.fBase;
84 if (base.fKind == Expression::kVariableReference_Kind) {
85 int builtin = ((VariableReference&) base).fVariable.fModifiers.fLayout.fBuiltin;
86 if (SK_TRANSFORMEDCOORDS2D_BUILTIN == builtin) {
87 this->write("%s");
88 if (i.fIndex->fKind != Expression::kIntLiteral_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070089 fErrors.error(i.fIndex->fOffset,
Ethan Nicholas762466e2017-06-29 10:03:38 -040090 "index into sk_TransformedCoords2D must be an integer literal");
91 return;
92 }
93 int64_t index = ((IntLiteral&) *i.fIndex).fValue;
94 String name = "sk_TransformedCoords2D_" + to_string(index);
95 fFormatArgs.push_back(name + ".c_str()");
96 if (fWrittenTransformedCoords.find(index) == fWrittenTransformedCoords.end()) {
Brian Osman72a37be2017-08-15 09:19:53 -040097 fExtraEmitCodeCode += " SkString " + name +
Ethan Nicholas762466e2017-06-29 10:03:38 -040098 " = fragBuilder->ensureCoords2D(args.fTransformedCoords[" +
99 to_string(index) + "]);\n";
100 fWrittenTransformedCoords.insert(index);
101 }
102 return;
103 } else if (SK_TEXTURESAMPLERS_BUILTIN == builtin) {
104 this->write("%s");
105 if (i.fIndex->fKind != Expression::kIntLiteral_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700106 fErrors.error(i.fIndex->fOffset,
Ethan Nicholas762466e2017-06-29 10:03:38 -0400107 "index into sk_TextureSamplers must be an integer literal");
108 return;
109 }
110 int64_t index = ((IntLiteral&) *i.fIndex).fValue;
111 fFormatArgs.push_back(" fragBuilder->getProgramBuilder()->samplerVariable("
112 "args.fTexSamplers[" + to_string(index) + "]).c_str()");
113 return;
114 }
115 }
116 INHERITED::writeIndexExpression(i);
117}
118
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400119static String default_value(const Type& type) {
Ethan Nicholase9d172a2017-11-20 12:12:24 -0500120 if (type.fName == "bool") {
121 return "false";
122 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400123 switch (type.kind()) {
124 case Type::kScalar_Kind: return "0";
125 case Type::kVector_Kind: return type.name() + "(0)";
126 case Type::kMatrix_Kind: return type.name() + "(1)";
127 default: ABORT("unsupported default_value type\n");
128 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400129}
130
Ethan Nicholase9d172a2017-11-20 12:12:24 -0500131static String default_value(const Variable& var) {
132 if (var.fModifiers.fLayout.fCType == "GrColor4f") {
133 return "GrColor4f::kIllegalConstructor";
134 }
135 return default_value(var.fType);
136}
137
Ethan Nicholas762466e2017-06-29 10:03:38 -0400138static bool is_private(const Variable& var) {
139 return !(var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
140 !(var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
141 var.fStorage == Variable::kGlobal_Storage &&
142 var.fModifiers.fLayout.fBuiltin == -1;
143}
144
Ethan Nicholasd608c092017-10-26 09:30:08 -0400145void CPPCodeGenerator::writeRuntimeValue(const Type& type, const Layout& layout,
146 const String& cppCode) {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400147 if (type.isFloat()) {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400148 this->write("%f");
149 fFormatArgs.push_back(cppCode);
150 } else if (type == *fContext.fInt_Type) {
151 this->write("%d");
152 fFormatArgs.push_back(cppCode);
153 } else if (type == *fContext.fBool_Type) {
154 this->write("%s");
155 fFormatArgs.push_back("(" + cppCode + " ? \"true\" : \"false\")");
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400156 } else if (type == *fContext.fFloat2_Type || type == *fContext.fHalf2_Type) {
157 this->write(type.name() + "(%f, %f)");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400158 fFormatArgs.push_back(cppCode + ".fX");
159 fFormatArgs.push_back(cppCode + ".fY");
Ethan Nicholas82399462017-10-16 12:35:44 -0400160 } else if (type == *fContext.fFloat4_Type || type == *fContext.fHalf4_Type) {
161 this->write(type.name() + "(%f, %f, %f, %f)");
Ethan Nicholasd608c092017-10-26 09:30:08 -0400162 if (layout.fCType == "SkPMColor") {
163 fFormatArgs.push_back("SkGetPackedR32(" + cppCode + ") / 255.0");
164 fFormatArgs.push_back("SkGetPackedG32(" + cppCode + ") / 255.0");
165 fFormatArgs.push_back("SkGetPackedB32(" + cppCode + ") / 255.0");
166 fFormatArgs.push_back("SkGetPackedA32(" + cppCode + ") / 255.0");
Ethan Nicholase9d172a2017-11-20 12:12:24 -0500167 } else if (layout.fCType == "GrColor4f") {
168 fFormatArgs.push_back(cppCode + ".fRGBA[0]");
169 fFormatArgs.push_back(cppCode + ".fRGBA[1]");
170 fFormatArgs.push_back(cppCode + ".fRGBA[2]");
171 fFormatArgs.push_back(cppCode + ".fRGBA[3]");
Ethan Nicholasd608c092017-10-26 09:30:08 -0400172 } else {
173 fFormatArgs.push_back(cppCode + ".left()");
174 fFormatArgs.push_back(cppCode + ".top()");
175 fFormatArgs.push_back(cppCode + ".right()");
176 fFormatArgs.push_back(cppCode + ".bottom()");
177 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500178 } else if (type.kind() == Type::kEnum_Kind) {
179 this->write("%d");
180 fFormatArgs.push_back("(int) " + cppCode);
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400181 } else if (type == *fContext.fInt4_Type ||
182 type == *fContext.fShort4_Type ||
183 type == *fContext.fByte4_Type) {
Ethan Nicholas2d5f9b32017-12-13 14:36:14 -0500184 this->write(type.name() + "(%d, %d, %d, %d)");
185 fFormatArgs.push_back(cppCode + ".left()");
186 fFormatArgs.push_back(cppCode + ".top()");
187 fFormatArgs.push_back(cppCode + ".right()");
188 fFormatArgs.push_back(cppCode + ".bottom()");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400189 } else {
Ethan Nicholas82399462017-10-16 12:35:44 -0400190 printf("unsupported runtime value type '%s'\n", String(type.fName).c_str());
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400191 SkASSERT(false);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400192 }
193}
194
195void CPPCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
196 if (is_private(var)) {
Ethan Nicholasd608c092017-10-26 09:30:08 -0400197 this->writeRuntimeValue(var.fType, var.fModifiers.fLayout, var.fName);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400198 } else {
199 this->writeExpression(value, kTopLevel_Precedence);
200 }
201}
202
Ethan Nicholasceb4d482017-07-10 15:40:20 -0400203String CPPCodeGenerator::getSamplerHandle(const Variable& var) {
204 int samplerCount = 0;
Ethan Nicholas68990be2017-07-13 09:36:52 -0400205 for (const auto param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholasceb4d482017-07-10 15:40:20 -0400206 if (&var == param) {
207 return "args.fTexSamplers[" + to_string(samplerCount) + "]";
208 }
209 if (param->fType.kind() == Type::kSampler_Kind) {
210 ++samplerCount;
211 }
212 }
213 ABORT("should have found sampler in parameters\n");
214}
215
Ethan Nicholasdcba08e2017-08-02 10:52:54 -0400216void CPPCodeGenerator::writeIntLiteral(const IntLiteral& i) {
217 this->write(to_string((int32_t) i.fValue));
218}
219
Ethan Nicholas82399462017-10-16 12:35:44 -0400220void CPPCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
221 if (fCPPMode) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400222 SkASSERT(swizzle.fComponents.size() == 1); // no support for multiple swizzle components yet
Ethan Nicholas82399462017-10-16 12:35:44 -0400223 this->writeExpression(*swizzle.fBase, kPostfix_Precedence);
224 switch (swizzle.fComponents[0]) {
225 case 0: this->write(".left()"); break;
226 case 1: this->write(".top()"); break;
227 case 2: this->write(".right()"); break;
228 case 3: this->write(".bottom()"); break;
229 }
230 } else {
231 INHERITED::writeSwizzle(swizzle);
232 }
233}
234
Ethan Nicholas762466e2017-06-29 10:03:38 -0400235void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
Ethan Nicholas82399462017-10-16 12:35:44 -0400236 if (fCPPMode) {
237 this->write(ref.fVariable.fName);
238 return;
239 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400240 switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
241 case SK_INCOLOR_BUILTIN:
242 this->write("%s");
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400243 fFormatArgs.push_back(String("args.fInputColor ? args.fInputColor : \"half4(1)\""));
Ethan Nicholas762466e2017-06-29 10:03:38 -0400244 break;
245 case SK_OUTCOLOR_BUILTIN:
246 this->write("%s");
247 fFormatArgs.push_back(String("args.fOutputColor"));
248 break;
Ethan Nicholascd700e92018-08-24 16:43:57 -0400249 case SK_WIDTH_BUILTIN:
250 this->write("sk_Width");
251 break;
252 case SK_HEIGHT_BUILTIN:
253 this->write("sk_Height");
254 break;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400255 default:
256 if (ref.fVariable.fType.kind() == Type::kSampler_Kind) {
Ethan Nicholasceb4d482017-07-10 15:40:20 -0400257 this->write("%s");
258 fFormatArgs.push_back("fragBuilder->getProgramBuilder()->samplerVariable(" +
259 this->getSamplerHandle(ref.fVariable) + ").c_str()");
260 return;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400261 }
262 if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) {
263 this->write("%s");
264 String name = ref.fVariable.fName;
Brian Osman1cb41712017-10-19 12:54:52 -0400265 String var = String::printf("args.fUniformHandler->getUniformCStr(%sVar)",
266 HCodeGenerator::FieldName(name.c_str()).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400267 String code;
268 if (ref.fVariable.fModifiers.fLayout.fWhen.size()) {
269 code = String::printf("%sVar.isValid() ? %s : \"%s\"",
270 HCodeGenerator::FieldName(name.c_str()).c_str(),
271 var.c_str(),
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400272 default_value(ref.fVariable.fType).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400273 } else {
274 code = var;
275 }
276 fFormatArgs.push_back(code);
277 } else if (SectionAndParameterHelper::IsParameter(ref.fVariable)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700278 String name(ref.fVariable.fName);
Ethan Nicholasd608c092017-10-26 09:30:08 -0400279 this->writeRuntimeValue(ref.fVariable.fType, ref.fVariable.fModifiers.fLayout,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700280 String::printf("_outer.%s()", name.c_str()).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400281 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700282 this->write(ref.fVariable.fName);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400283 }
284 }
285}
286
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -0400287void CPPCodeGenerator::writeIfStatement(const IfStatement& s) {
288 if (s.fIsStatic) {
289 this->write("@");
290 }
291 INHERITED::writeIfStatement(s);
292}
293
Ethan Nicholasf1b14642018-08-09 16:18:07 -0400294void CPPCodeGenerator::writeReturnStatement(const ReturnStatement& s) {
295 if (fInMain) {
296 fErrors.error(s.fOffset, "fragmentProcessor main() may not contain return statements");
297 }
298 INHERITED::writeReturnStatement(s);
299}
300
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -0400301void CPPCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
302 if (s.fIsStatic) {
303 this->write("@");
304 }
305 INHERITED::writeSwitchStatement(s);
306}
307
Ethan Nicholasceb4d482017-07-10 15:40:20 -0400308void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400309 if (c.fFunction.fBuiltin && c.fFunction.fName == "process") {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400310 SkASSERT(c.fArguments.size() == 1);
311 SkASSERT(Expression::kVariableReference_Kind == c.fArguments[0]->fKind);
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400312 int index = 0;
313 bool found = false;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400314 for (const auto& p : fProgram) {
315 if (ProgramElement::kVar_Kind == p.fKind) {
316 const VarDeclarations& decls = (const VarDeclarations&) p;
317 for (const auto& raw : decls.fVars) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000318 VarDeclaration& decl = (VarDeclaration&) *raw;
319 if (decl.fVar == &((VariableReference&) *c.fArguments[0]).fVariable) {
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400320 found = true;
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000321 } else if (decl.fVar->fType == *fContext.fFragmentProcessor_Type) {
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400322 ++index;
323 }
324 }
325 }
326 if (found) {
327 break;
328 }
329 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400330 SkASSERT(found);
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400331 String childName = "_child" + to_string(index);
332 fExtraEmitCodeCode += " SkString " + childName + "(\"" + childName + "\");\n" +
333 " this->emitChild(" + to_string(index) + ", &" + childName +
334 ", args);\n";
335 this->write("%s");
336 fFormatArgs.push_back(childName + ".c_str()");
337 return;
338 }
Ethan Nicholasceb4d482017-07-10 15:40:20 -0400339 INHERITED::writeFunctionCall(c);
340 if (c.fFunction.fBuiltin && c.fFunction.fName == "texture") {
341 this->write(".%s");
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400342 SkASSERT(c.fArguments.size() >= 1);
343 SkASSERT(c.fArguments[0]->fKind == Expression::kVariableReference_Kind);
Ethan Nicholasceb4d482017-07-10 15:40:20 -0400344 String sampler = this->getSamplerHandle(((VariableReference&) *c.fArguments[0]).fVariable);
345 fFormatArgs.push_back("fragBuilder->getProgramBuilder()->samplerSwizzle(" + sampler +
346 ").c_str()");
347 }
348}
349
Ethan Nicholas762466e2017-06-29 10:03:38 -0400350void CPPCodeGenerator::writeFunction(const FunctionDefinition& f) {
351 if (f.fDeclaration.fName == "main") {
352 fFunctionHeader = "";
353 OutputStream* oldOut = fOut;
354 StringStream buffer;
355 fOut = &buffer;
Ethan Nicholasf1b14642018-08-09 16:18:07 -0400356 fInMain = true;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400357 for (const auto& s : ((Block&) *f.fBody).fStatements) {
358 this->writeStatement(*s);
359 this->writeLine();
360 }
Ethan Nicholasf1b14642018-08-09 16:18:07 -0400361 fInMain = false;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400362
363 fOut = oldOut;
364 this->write(fFunctionHeader);
365 this->write(buffer.str());
366 } else {
367 INHERITED::writeFunction(f);
368 }
369}
370
371void CPPCodeGenerator::writeSetting(const Setting& s) {
372 static constexpr const char* kPrefix = "sk_Args.";
373 if (!strncmp(s.fName.c_str(), kPrefix, strlen(kPrefix))) {
374 const char* name = s.fName.c_str() + strlen(kPrefix);
Ethan Nicholasd608c092017-10-26 09:30:08 -0400375 this->writeRuntimeValue(s.fType, Layout(), HCodeGenerator::FieldName(name).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400376 } else {
377 this->write(s.fName.c_str());
378 }
379}
380
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400381bool CPPCodeGenerator::writeSection(const char* name, const char* prefix) {
Ethan Nicholas68990be2017-07-13 09:36:52 -0400382 const Section* s = fSectionAndParameterHelper.getSection(name);
383 if (s) {
384 this->writef("%s%s", prefix, s->fText.c_str());
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400385 return true;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400386 }
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400387 return false;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400388}
389
390void CPPCodeGenerator::writeProgramElement(const ProgramElement& p) {
391 if (p.fKind == ProgramElement::kSection_Kind) {
392 return;
393 }
394 if (p.fKind == ProgramElement::kVar_Kind) {
395 const VarDeclarations& decls = (const VarDeclarations&) p;
396 if (!decls.fVars.size()) {
397 return;
398 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000399 const Variable& var = *((VarDeclaration&) *decls.fVars[0]).fVar;
Ethan Nicholas762466e2017-06-29 10:03:38 -0400400 if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) ||
401 -1 != var.fModifiers.fLayout.fBuiltin) {
402 return;
403 }
404 }
405 INHERITED::writeProgramElement(p);
406}
407
408void CPPCodeGenerator::addUniform(const Variable& var) {
409 if (!needs_uniform_var(var)) {
410 return;
411 }
412 const char* precision;
413 if (var.fModifiers.fFlags & Modifiers::kHighp_Flag) {
414 precision = "kHigh_GrSLPrecision";
415 } else if (var.fModifiers.fFlags & Modifiers::kMediump_Flag) {
416 precision = "kMedium_GrSLPrecision";
417 } else if (var.fModifiers.fFlags & Modifiers::kLowp_Flag) {
418 precision = "kLow_GrSLPrecision";
419 } else {
420 precision = "kDefault_GrSLPrecision";
421 }
422 const char* type;
423 if (var.fType == *fContext.fFloat_Type) {
Ethan Nicholas8aa45692017-09-20 11:24:15 -0400424 type = "kFloat_GrSLType";
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400425 } else if (var.fType == *fContext.fHalf_Type) {
426 type = "kHalf_GrSLType";
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400427 } else if (var.fType == *fContext.fFloat2_Type) {
Ethan Nicholas8aa45692017-09-20 11:24:15 -0400428 type = "kFloat2_GrSLType";
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400429 } else if (var.fType == *fContext.fHalf2_Type) {
430 type = "kHalf2_GrSLType";
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400431 } else if (var.fType == *fContext.fFloat4_Type) {
Ethan Nicholas8aa45692017-09-20 11:24:15 -0400432 type = "kFloat4_GrSLType";
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400433 } else if (var.fType == *fContext.fHalf4_Type) {
434 type = "kHalf4_GrSLType";
Brian Osman1cb41712017-10-19 12:54:52 -0400435 } else if (var.fType == *fContext.fFloat4x4_Type) {
Ethan Nicholas8aa45692017-09-20 11:24:15 -0400436 type = "kFloat4x4_GrSLType";
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400437 } else if (var.fType == *fContext.fHalf4x4_Type) {
438 type = "kHalf4x4_GrSLType";
Ethan Nicholas762466e2017-06-29 10:03:38 -0400439 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700440 ABORT("unsupported uniform type: %s %s;\n", String(var.fType.fName).c_str(),
441 String(var.fName).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400442 }
443 if (var.fModifiers.fLayout.fWhen.size()) {
444 this->writef(" if (%s) {\n ", var.fModifiers.fLayout.fWhen.c_str());
445 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700446 String name(var.fName);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400447 this->writef(" %sVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, %s, "
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700448 "%s, \"%s\");\n", HCodeGenerator::FieldName(name.c_str()).c_str(), type, precision,
449 name.c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400450 if (var.fModifiers.fLayout.fWhen.size()) {
451 this->write(" }\n");
452 }
453}
454
Ethan Nicholascd700e92018-08-24 16:43:57 -0400455void CPPCodeGenerator::writeInputVars() {
456}
457
Ethan Nicholas762466e2017-06-29 10:03:38 -0400458void CPPCodeGenerator::writePrivateVars() {
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400459 for (const auto& p : fProgram) {
460 if (ProgramElement::kVar_Kind == p.fKind) {
461 const VarDeclarations& decls = (const VarDeclarations&) p;
462 for (const auto& raw : decls.fVars) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000463 VarDeclaration& decl = (VarDeclaration&) *raw;
464 if (is_private(*decl.fVar)) {
465 if (decl.fVar->fType == *fContext.fFragmentProcessor_Type) {
466 fErrors.error(decl.fOffset,
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400467 "fragmentProcessor variables must be declared 'in'");
468 return;
469 }
Ethan Nicholase9d172a2017-11-20 12:12:24 -0500470 this->writef("%s %s = %s;\n",
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000471 HCodeGenerator::FieldType(fContext, decl.fVar->fType,
472 decl.fVar->fModifiers.fLayout).c_str(),
Ethan Nicholase9d172a2017-11-20 12:12:24 -0500473 String(decl.fVar->fName).c_str(),
474 default_value(*decl.fVar).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400475 }
476 }
477 }
478 }
479}
480
481void CPPCodeGenerator::writePrivateVarValues() {
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400482 for (const auto& p : fProgram) {
483 if (ProgramElement::kVar_Kind == p.fKind) {
484 const VarDeclarations& decls = (const VarDeclarations&) p;
485 for (const auto& raw : decls.fVars) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000486 VarDeclaration& decl = (VarDeclaration&) *raw;
487 if (is_private(*decl.fVar) && decl.fValue) {
488 this->writef("%s = ", String(decl.fVar->fName).c_str());
Ethan Nicholas82399462017-10-16 12:35:44 -0400489 fCPPMode = true;
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000490 this->writeExpression(*decl.fValue, kAssignment_Precedence);
Ethan Nicholas82399462017-10-16 12:35:44 -0400491 fCPPMode = false;
492 this->write(";\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400493 }
494 }
495 }
496 }
497}
498
Ethan Nicholas82399462017-10-16 12:35:44 -0400499static bool is_accessible(const Variable& var) {
500 return Type::kSampler_Kind != var.fType.kind() &&
501 Type::kOther_Kind != var.fType.kind();
502}
503
Ethan Nicholas5b6e6272017-10-13 13:11:06 -0400504void CPPCodeGenerator::writeCodeAppend(const String& code) {
505 // codeAppendf can only handle appending 1024 bytes at a time, so we need to break the string
506 // into chunks. Unfortunately we can't tell exactly how long the string is going to end up,
507 // because printf escape sequences get replaced by strings of unknown length, but keeping the
508 // format string below 512 bytes is probably safe.
509 static constexpr size_t maxChunkSize = 512;
510 size_t start = 0;
511 size_t index = 0;
512 size_t argStart = 0;
513 size_t argCount;
514 while (index < code.size()) {
515 argCount = 0;
516 this->write(" fragBuilder->codeAppendf(\"");
517 while (index < code.size() && index < start + maxChunkSize) {
518 if ('%' == code[index]) {
519 if (index == start + maxChunkSize - 1 || index == code.size() - 1) {
520 break;
521 }
522 if (code[index + 1] != '%') {
523 ++argCount;
524 }
Ethan Nicholasef0c9fd2017-10-30 10:04:14 -0400525 } else if ('\\' == code[index] && index == start + maxChunkSize - 1) {
526 // avoid splitting an escape sequence that happens to fall across a chunk boundary
527 break;
Ethan Nicholas5b6e6272017-10-13 13:11:06 -0400528 }
529 ++index;
530 }
531 fOut->write(code.c_str() + start, index - start);
532 this->write("\"");
533 for (size_t i = argStart; i < argStart + argCount; ++i) {
534 this->writef(", %s", fFormatArgs[i].c_str());
535 }
536 this->write(");\n");
537 argStart += argCount;
538 start = index;
539 }
540}
541
Ethan Nicholas762466e2017-06-29 10:03:38 -0400542bool CPPCodeGenerator::writeEmitCode(std::vector<const Variable*>& uniforms) {
543 this->write(" void emitCode(EmitArgs& args) override {\n"
544 " GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n");
545 this->writef(" const %s& _outer = args.fFp.cast<%s>();\n"
546 " (void) _outer;\n",
547 fFullName.c_str(), fFullName.c_str());
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400548 for (const auto& p : fProgram) {
549 if (ProgramElement::kVar_Kind == p.fKind) {
550 const VarDeclarations& decls = (const VarDeclarations&) p;
551 for (const auto& raw : decls.fVars) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000552 VarDeclaration& decl = (VarDeclaration&) *raw;
553 String nameString(decl.fVar->fName);
Ethan Nicholas82399462017-10-16 12:35:44 -0400554 const char* name = nameString.c_str();
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000555 if (SectionAndParameterHelper::IsParameter(*decl.fVar) &&
556 is_accessible(*decl.fVar)) {
Ethan Nicholas82399462017-10-16 12:35:44 -0400557 this->writef(" auto %s = _outer.%s();\n"
558 " (void) %s;\n",
559 name, name, name);
560 }
561 }
562 }
563 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400564 this->writePrivateVarValues();
565 for (const auto u : uniforms) {
566 this->addUniform(*u);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400567 }
568 this->writeSection(EMIT_CODE_SECTION);
569 OutputStream* old = fOut;
570 StringStream mainBuffer;
571 fOut = &mainBuffer;
572 bool result = INHERITED::generateCode();
573 fOut = old;
Ethan Nicholas5b6e6272017-10-13 13:11:06 -0400574 this->writef("%s", fExtraEmitCodeCode.c_str());
575 this->writeCodeAppend(mainBuffer.str());
576 this->write(" }\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400577 return result;
578}
579
580void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
581 const char* fullName = fFullName.c_str();
Ethan Nicholas68990be2017-07-13 09:36:52 -0400582 const Section* section = fSectionAndParameterHelper.getSection(SET_DATA_SECTION);
583 const char* pdman = section ? section->fArgument.c_str() : "pdman";
Ethan Nicholas762466e2017-06-29 10:03:38 -0400584 this->writef(" void onSetData(const GrGLSLProgramDataManager& %s, "
585 "const GrFragmentProcessor& _proc) override {\n",
586 pdman);
587 bool wroteProcessor = false;
588 for (const auto u : uniforms) {
589 if (u->fModifiers.fFlags & Modifiers::kIn_Flag) {
590 if (!wroteProcessor) {
591 this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName, fullName);
592 wroteProcessor = true;
593 this->writef(" {\n");
594 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700595 String nameString(u->fName);
596 const char* name = nameString.c_str();
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400597 if (u->fType == *fContext.fFloat4_Type || u->fType == *fContext.fHalf4_Type) {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400598 this->writef(" const SkRect %sValue = _outer.%s();\n"
Ethan Nicholasee338732017-07-17 15:13:45 -0400599 " %s.set4fv(%sVar, 1, (float*) &%sValue);\n",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400600 name, name, pdman, HCodeGenerator::FieldName(name).c_str(), name);
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400601 } else if (u->fType == *fContext.fFloat4x4_Type ||
602 u->fType == *fContext.fHalf4x4_Type) {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400603 this->writef(" float %sValue[16];\n"
604 " _outer.%s().asColMajorf(%sValue);\n"
605 " %s.setMatrix4f(%sVar, %sValue);\n",
606 name, name, name, pdman, HCodeGenerator::FieldName(name).c_str(),
607 name);
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400608 } else if (u->fType == *fContext.fFragmentProcessor_Type) {
609 // do nothing
Ethan Nicholas762466e2017-06-29 10:03:38 -0400610 } else {
611 this->writef(" %s.set1f(%sVar, _outer.%s());\n",
612 pdman, HCodeGenerator::FieldName(name).c_str(), name);
613 }
614 }
615 }
616 if (wroteProcessor) {
617 this->writef(" }\n");
618 }
Ethan Nicholas68990be2017-07-13 09:36:52 -0400619 if (section) {
Ethan Nicholas2d5f9b32017-12-13 14:36:14 -0500620 int samplerIndex = 0;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400621 for (const auto& p : fProgram) {
622 if (ProgramElement::kVar_Kind == p.fKind) {
623 const VarDeclarations& decls = (const VarDeclarations&) p;
624 for (const auto& raw : decls.fVars) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000625 VarDeclaration& decl = (VarDeclaration&) *raw;
626 String nameString(decl.fVar->fName);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700627 const char* name = nameString.c_str();
Ethan Nicholas2d5f9b32017-12-13 14:36:14 -0500628 if (decl.fVar->fType.kind() == Type::kSampler_Kind) {
629 this->writef(" GrSurfaceProxy& %sProxy = "
630 "*_outer.textureSampler(%d).proxy();\n",
631 name, samplerIndex);
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400632 this->writef(" GrTexture& %s = *%sProxy.peekTexture();\n",
Ethan Nicholas2d5f9b32017-12-13 14:36:14 -0500633 name, name);
634 this->writef(" (void) %s;\n", name);
635 ++samplerIndex;
636 } else if (needs_uniform_var(*decl.fVar)) {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400637 this->writef(" UniformHandle& %s = %sVar;\n"
638 " (void) %s;\n",
639 name, HCodeGenerator::FieldName(name).c_str(), name);
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000640 } else if (SectionAndParameterHelper::IsParameter(*decl.fVar) &&
641 decl.fVar->fType != *fContext.fFragmentProcessor_Type) {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400642 if (!wroteProcessor) {
643 this->writef(" const %s& _outer = _proc.cast<%s>();\n", fullName,
644 fullName);
645 wroteProcessor = true;
646 }
647 this->writef(" auto %s = _outer.%s();\n"
648 " (void) %s;\n",
649 name, name, name);
650 }
651 }
652 }
653 }
654 this->writeSection(SET_DATA_SECTION);
655 }
656 this->write(" }\n");
657}
658
Brian Salomonf7dcd762018-07-30 14:48:15 -0400659void CPPCodeGenerator::writeOnTextureSampler() {
660 bool foundSampler = false;
661 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
662 if (param->fType.kind() == Type::kSampler_Kind) {
663 if (!foundSampler) {
664 this->writef(
665 "const GrFragmentProcessor::TextureSampler& %s::onTextureSampler(int "
666 "index) const {\n",
667 fFullName.c_str());
668 this->writef(" return IthTextureSampler(index, %s",
669 HCodeGenerator::FieldName(String(param->fName).c_str()).c_str());
670 foundSampler = true;
671 } else {
672 this->writef(", %s",
673 HCodeGenerator::FieldName(String(param->fName).c_str()).c_str());
674 }
675 }
676 }
677 if (foundSampler) {
678 this->write(");\n}\n");
679 }
680}
681
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400682void CPPCodeGenerator::writeClone() {
683 if (!this->writeSection(CLONE_SECTION)) {
684 if (fSectionAndParameterHelper.getSection(FIELDS_SECTION)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700685 fErrors.error(0, "fragment processors with custom @fields must also have a custom"
686 "@clone");
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400687 }
688 this->writef("%s::%s(const %s& src)\n"
Ethan Nicholasabff9562017-10-09 10:54:08 -0400689 ": INHERITED(k%s_ClassID, src.optimizationFlags())", fFullName.c_str(),
690 fFullName.c_str(), fFullName.c_str(), fFullName.c_str());
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400691 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400692 if (param->fType == *fContext.fFragmentProcessor_Type) {
693 continue;
694 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700695 String fieldName = HCodeGenerator::FieldName(String(param->fName).c_str());
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400696 this->writef("\n, %s(src.%s)",
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400697 fieldName.c_str(),
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400698 fieldName.c_str());
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400699 }
Ethan Nicholas929a6812018-08-06 14:56:59 -0400700 const auto transforms = fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION);
701 for (size_t i = 0; i < transforms.size(); ++i) {
702 const Section& s = *transforms[i];
703 String fieldName = HCodeGenerator::CoordTransformName(s.fArgument, i);
704 this->writef("\n, %s(src.%s)", fieldName.c_str(), fieldName.c_str());
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400705 }
Ethan Nicholasabff9562017-10-09 10:54:08 -0400706 this->writef(" {\n");
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400707 int childCount = 0;
Brian Salomonf7dcd762018-07-30 14:48:15 -0400708 int samplerCount = 0;
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400709 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
710 if (param->fType.kind() == Type::kSampler_Kind) {
Brian Salomonf7dcd762018-07-30 14:48:15 -0400711 ++samplerCount;
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400712 } else if (param->fType == *fContext.fFragmentProcessor_Type) {
713 this->writef(" this->registerChildProcessor(src.childProcessor(%d).clone());"
714 "\n", childCount++);
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400715 }
716 }
Brian Salomonf7dcd762018-07-30 14:48:15 -0400717 if (samplerCount) {
718 this->writef(" this->setTextureSamplerCnt(%d);", samplerCount);
719 }
Ethan Nicholas929a6812018-08-06 14:56:59 -0400720 for (size_t i = 0; i < transforms.size(); ++i) {
721 const Section& s = *transforms[i];
722 String fieldName = HCodeGenerator::CoordTransformName(s.fArgument, i);
723 this->writef(" this->addCoordTransform(&%s);\n", fieldName.c_str());
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400724 }
725 this->write("}\n");
Brian Salomonaff329b2017-08-11 09:40:37 -0400726 this->writef("std::unique_ptr<GrFragmentProcessor> %s::clone() const {\n",
727 fFullName.c_str());
728 this->writef(" return std::unique_ptr<GrFragmentProcessor>(new %s(*this));\n",
729 fFullName.c_str());
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400730 this->write("}\n");
731 }
732}
733
Ethan Nicholas762466e2017-06-29 10:03:38 -0400734void CPPCodeGenerator::writeTest() {
Ethan Nicholas68990be2017-07-13 09:36:52 -0400735 const Section* test = fSectionAndParameterHelper.getSection(TEST_CODE_SECTION);
736 if (test) {
Brian Salomonaff329b2017-08-11 09:40:37 -0400737 this->writef(
738 "GR_DEFINE_FRAGMENT_PROCESSOR_TEST(%s);\n"
739 "#if GR_TEST_UTILS\n"
740 "std::unique_ptr<GrFragmentProcessor> %s::TestCreate(GrProcessorTestData* %s) {\n",
741 fFullName.c_str(),
742 fFullName.c_str(),
743 test->fArgument.c_str());
Ethan Nicholas68990be2017-07-13 09:36:52 -0400744 this->writeSection(TEST_CODE_SECTION);
745 this->write("}\n"
746 "#endif\n");
Ethan Nicholas762466e2017-06-29 10:03:38 -0400747 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400748}
749
750void CPPCodeGenerator::writeGetKey() {
751 this->writef("void %s::onGetGLSLProcessorKey(const GrShaderCaps& caps, "
752 "GrProcessorKeyBuilder* b) const {\n",
753 fFullName.c_str());
Ethan Nicholas68990be2017-07-13 09:36:52 -0400754 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700755 String nameString(param->fName);
756 const char* name = nameString.c_str();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400757 if (param->fModifiers.fLayout.fKey != Layout::kNo_Key &&
758 (param->fModifiers.fFlags & Modifiers::kUniform_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700759 fErrors.error(param->fOffset,
Ethan Nicholas762466e2017-06-29 10:03:38 -0400760 "layout(key) may not be specified on uniforms");
761 }
762 switch (param->fModifiers.fLayout.fKey) {
763 case Layout::kKey_Key:
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400764 if (param->fType == *fContext.fFloat4x4_Type) {
765 ABORT("no automatic key handling for float4x4\n");
766 } else if (param->fType == *fContext.fFloat2_Type) {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400767 this->writef(" b->add32(%s.fX);\n",
768 HCodeGenerator::FieldName(name).c_str());
769 this->writef(" b->add32(%s.fY);\n",
770 HCodeGenerator::FieldName(name).c_str());
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400771 } else if (param->fType == *fContext.fFloat4_Type) {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400772 this->writef(" b->add32(%s.x());\n",
773 HCodeGenerator::FieldName(name).c_str());
774 this->writef(" b->add32(%s.y());\n",
775 HCodeGenerator::FieldName(name).c_str());
776 this->writef(" b->add32(%s.width());\n",
777 HCodeGenerator::FieldName(name).c_str());
778 this->writef(" b->add32(%s.height());\n",
779 HCodeGenerator::FieldName(name).c_str());
780 } else {
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500781 this->writef(" b->add32((int32_t) %s);\n",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400782 HCodeGenerator::FieldName(name).c_str());
783 }
784 break;
785 case Layout::kIdentity_Key:
786 if (param->fType.kind() != Type::kMatrix_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700787 fErrors.error(param->fOffset,
Ethan Nicholas762466e2017-06-29 10:03:38 -0400788 "layout(key=identity) requires matrix type");
789 }
790 this->writef(" b->add32(%s.isIdentity() ? 1 : 0);\n",
791 HCodeGenerator::FieldName(name).c_str());
792 break;
793 case Layout::kNo_Key:
794 break;
795 }
796 }
797 this->write("}\n");
798}
799
800bool CPPCodeGenerator::generateCode() {
801 std::vector<const Variable*> uniforms;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400802 for (const auto& p : fProgram) {
803 if (ProgramElement::kVar_Kind == p.fKind) {
804 const VarDeclarations& decls = (const VarDeclarations&) p;
805 for (const auto& raw : decls.fVars) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000806 VarDeclaration& decl = (VarDeclaration&) *raw;
807 if ((decl.fVar->fModifiers.fFlags & Modifiers::kUniform_Flag) &&
808 decl.fVar->fType.kind() != Type::kSampler_Kind) {
809 uniforms.push_back(decl.fVar);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400810 }
811 }
812 }
813 }
814 const char* baseName = fName.c_str();
815 const char* fullName = fFullName.c_str();
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500816 this->writef("%s\n", HCodeGenerator::GetHeader(fProgram, fErrors).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400817 this->writef(kFragmentProcessorHeader, fullName);
Greg Daniel3e8c3452018-04-06 10:37:55 -0400818 this->writef("#include \"%s.h\"\n", fullName);
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400819 this->writeSection(CPP_SECTION);
Brian Osman1cb41712017-10-19 12:54:52 -0400820 this->writef("#include \"glsl/GrGLSLFragmentProcessor.h\"\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400821 "#include \"glsl/GrGLSLFragmentShaderBuilder.h\"\n"
822 "#include \"glsl/GrGLSLProgramBuilder.h\"\n"
Ethan Nicholas2d5f9b32017-12-13 14:36:14 -0500823 "#include \"GrTexture.h\"\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400824 "#include \"SkSLCPP.h\"\n"
825 "#include \"SkSLUtil.h\"\n"
826 "class GrGLSL%s : public GrGLSLFragmentProcessor {\n"
827 "public:\n"
828 " GrGLSL%s() {}\n",
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400829 baseName, baseName);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400830 bool result = this->writeEmitCode(uniforms);
831 this->write("private:\n");
832 this->writeSetData(uniforms);
833 this->writePrivateVars();
834 for (const auto& u : uniforms) {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400835 if (needs_uniform_var(*u) && !(u->fModifiers.fFlags & Modifiers::kIn_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700836 this->writef(" UniformHandle %sVar;\n",
837 HCodeGenerator::FieldName(String(u->fName).c_str()).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400838 }
839 }
Ethan Nicholas68990be2017-07-13 09:36:52 -0400840 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholas762466e2017-06-29 10:03:38 -0400841 if (needs_uniform_var(*param)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700842 this->writef(" UniformHandle %sVar;\n",
843 HCodeGenerator::FieldName(String(param->fName).c_str()).c_str());
Ethan Nicholas762466e2017-06-29 10:03:38 -0400844 }
845 }
Ethan Nicholas762466e2017-06-29 10:03:38 -0400846 this->writef("};\n"
847 "GrGLSLFragmentProcessor* %s::onCreateGLSLInstance() const {\n"
848 " return new GrGLSL%s();\n"
849 "}\n",
850 fullName, baseName);
851 this->writeGetKey();
852 this->writef("bool %s::onIsEqual(const GrFragmentProcessor& other) const {\n"
853 " const %s& that = other.cast<%s>();\n"
854 " (void) that;\n",
855 fullName, fullName, fullName);
Ethan Nicholas68990be2017-07-13 09:36:52 -0400856 for (const auto& param : fSectionAndParameterHelper.getParameters()) {
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400857 if (param->fType == *fContext.fFragmentProcessor_Type) {
858 continue;
859 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700860 String nameString(param->fName);
861 const char* name = nameString.c_str();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400862 this->writef(" if (%s != that.%s) return false;\n",
863 HCodeGenerator::FieldName(name).c_str(),
864 HCodeGenerator::FieldName(name).c_str());
865 }
866 this->write(" return true;\n"
867 "}\n");
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400868 this->writeClone();
Brian Salomonf7dcd762018-07-30 14:48:15 -0400869 this->writeOnTextureSampler();
Ethan Nicholas762466e2017-06-29 10:03:38 -0400870 this->writeTest();
Ethan Nicholas9fb036f2017-07-05 16:19:09 -0400871 this->writeSection(CPP_END_SECTION);
Greg Daniel3e8c3452018-04-06 10:37:55 -0400872
Ethan Nicholas762466e2017-06-29 10:03:38 -0400873 result &= 0 == fErrors.errorCount();
874 return result;
875}
876
877} // namespace