aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sksl/SkSLPipelineStageCodeGenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sksl/SkSLPipelineStageCodeGenerator.cpp')
-rw-r--r--src/sksl/SkSLPipelineStageCodeGenerator.cpp167
1 files changed, 167 insertions, 0 deletions
diff --git a/src/sksl/SkSLPipelineStageCodeGenerator.cpp b/src/sksl/SkSLPipelineStageCodeGenerator.cpp
new file mode 100644
index 0000000000..aceb75e3ee
--- /dev/null
+++ b/src/sksl/SkSLPipelineStageCodeGenerator.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkSLPipelineStageCodeGenerator.h"
+
+#include "SkSLCompiler.h"
+#include "SkSLHCodeGenerator.h"
+
+namespace SkSL {
+
+PipelineStageCodeGenerator::PipelineStageCodeGenerator(
+ const Context* context,
+ const Program* program,
+ ErrorReporter* errors,
+ OutputStream* out,
+ std::vector<Compiler::FormatArg>* outFormatArgs)
+: INHERITED(context, program, errors, out)
+, fName("Temp")
+, fFullName(String::printf("Gr%s", fName.c_str()))
+, fSectionAndParameterHelper(*program, *errors)
+, fFormatArgs(outFormatArgs) {}
+
+void PipelineStageCodeGenerator::writef(const char* s, va_list va) {
+ static constexpr int BUFFER_SIZE = 1024;
+ va_list copy;
+ va_copy(copy, va);
+ char buffer[BUFFER_SIZE];
+ int length = vsnprintf(buffer, BUFFER_SIZE, s, va);
+ if (length < BUFFER_SIZE) {
+ fOut->write(buffer, length);
+ } else {
+ std::unique_ptr<char[]> heap(new char[length + 1]);
+ vsprintf(heap.get(), s, copy);
+ fOut->write(heap.get(), length);
+ }
+}
+
+void PipelineStageCodeGenerator::writef(const char* s, ...) {
+ va_list va;
+ va_start(va, s);
+ this->writef(s, va);
+ va_end(va);
+}
+
+void PipelineStageCodeGenerator::writeHeader() {
+}
+
+bool PipelineStageCodeGenerator::usesPrecisionModifiers() const {
+ return false;
+}
+
+String PipelineStageCodeGenerator::getTypeName(const Type& type) {
+ return type.name();
+}
+
+void PipelineStageCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
+ Precedence parentPrecedence) {
+ if (b.fOperator == Token::PERCENT) {
+ // need to use "%%" instead of "%" b/c the code will be inside of a printf
+ Precedence precedence = GetBinaryPrecedence(b.fOperator);
+ if (precedence >= parentPrecedence) {
+ this->write("(");
+ }
+ this->writeExpression(*b.fLeft, precedence);
+ this->write(" %% ");
+ this->writeExpression(*b.fRight, precedence);
+ if (precedence >= parentPrecedence) {
+ this->write(")");
+ }
+ } else {
+ INHERITED::writeBinaryExpression(b, parentPrecedence);
+ }
+}
+
+void PipelineStageCodeGenerator::writeIntLiteral(const IntLiteral& i) {
+ this->write(to_string((int32_t) i.fValue));
+}
+
+void PipelineStageCodeGenerator::writeVariableReference(const VariableReference& ref) {
+ switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
+ case SK_INCOLOR_BUILTIN:
+ this->write("%s");
+ fFormatArgs->push_back(Compiler::FormatArg::kInput);
+ break;
+ case SK_OUTCOLOR_BUILTIN:
+ this->write("%s");
+ fFormatArgs->push_back(Compiler::FormatArg::kOutput);
+ break;
+ case SK_MAIN_X_BUILTIN:
+ this->write("sk_FragCoord.x");
+ break;
+ case SK_MAIN_Y_BUILTIN:
+ this->write("sk_FragCoord.y");
+ break;
+ default:
+ this->write(ref.fVariable.fName);
+ }
+}
+
+void PipelineStageCodeGenerator::writeIfStatement(const IfStatement& s) {
+ if (s.fIsStatic) {
+ this->write("@");
+ }
+ INHERITED::writeIfStatement(s);
+}
+
+void PipelineStageCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
+ if (s.fIsStatic) {
+ this->write("@");
+ }
+ INHERITED::writeSwitchStatement(s);
+}
+
+void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) {
+ if (f.fDeclaration.fName == "main") {
+ fFunctionHeader = "";
+ OutputStream* oldOut = fOut;
+ StringStream buffer;
+ fOut = &buffer;
+ this->write("%s = %s;\n");
+ fFormatArgs->push_back(Compiler::FormatArg::kOutput);
+ fFormatArgs->push_back(Compiler::FormatArg::kInput);
+ for (const auto& s : ((Block&) *f.fBody).fStatements) {
+ this->writeStatement(*s);
+ this->writeLine();
+ }
+
+ fOut = oldOut;
+ this->write(fFunctionHeader);
+ this->writef("%s", buffer.str().c_str());
+ } else {
+ INHERITED::writeFunction(f);
+ }
+}
+
+bool PipelineStageCodeGenerator::writeSection(const char* name, const char* prefix) {
+ const Section* s = fSectionAndParameterHelper.getSection(name);
+ if (s) {
+ this->writef("%s%s", prefix, s->fText.c_str());
+ return true;
+ }
+ return false;
+}
+
+void PipelineStageCodeGenerator::writeProgramElement(const ProgramElement& p) {
+ if (p.fKind == ProgramElement::kSection_Kind) {
+ return;
+ }
+ if (p.fKind == ProgramElement::kVar_Kind) {
+ const VarDeclarations& decls = (const VarDeclarations&) p;
+ if (!decls.fVars.size()) {
+ return;
+ }
+ const Variable& var = *((VarDeclaration&) *decls.fVars[0]).fVar;
+ if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) ||
+ -1 != var.fModifiers.fLayout.fBuiltin) {
+ return;
+ }
+ }
+ INHERITED::writeProgramElement(p);
+}
+
+} // namespace