aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sksl/SkSLIRGenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sksl/SkSLIRGenerator.cpp')
-rw-r--r--src/sksl/SkSLIRGenerator.cpp90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 68d9f9c0ca..815ec152cd 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -17,6 +17,7 @@
#include "ast/SkSLASTFloatLiteral.h"
#include "ast/SkSLASTIndexSuffix.h"
#include "ast/SkSLASTIntLiteral.h"
+#include "ir/SkSLAppendStage.h"
#include "ir/SkSLBinaryExpression.h"
#include "ir/SkSLBoolLiteral.h"
#include "ir/SkSLBreakStatement.h"
@@ -1971,6 +1972,91 @@ std::unique_ptr<Expression> IRGenerator::convertTypeField(int offset, const Type
return result;
}
+std::unique_ptr<Expression> IRGenerator::convertAppend(int offset,
+ const std::vector<std::unique_ptr<ASTExpression>>& args) {
+#ifndef SKSL_STANDALONE
+ if (args.size() < 2) {
+ fErrors.error(offset, "'append' requires at least two arguments");
+ return nullptr;
+ }
+ std::unique_ptr<Expression> pipeline = this->convertExpression(*args[0]);
+ if (!pipeline) {
+ return nullptr;
+ }
+ if (pipeline->fType != *fContext.fSkRasterPipeline_Type) {
+ fErrors.error(offset, "first argument of 'append' must have type 'SkRasterPipeline'");
+ return nullptr;
+ }
+ if (ASTExpression::kIdentifier_Kind != args[1]->fKind) {
+ fErrors.error(offset, "'" + args[1]->description() + "' is not a valid stage");
+ return nullptr;
+ }
+ StringFragment name = ((const ASTIdentifier&) *args[1]).fText;
+ SkRasterPipeline::StockStage stage = SkRasterPipeline::premul;
+ std::vector<std::unique_ptr<Expression>> stageArgs;
+ stageArgs.push_back(std::move(pipeline));
+ for (size_t i = 2; i < args.size(); ++i) {
+ std::unique_ptr<Expression> arg = this->convertExpression(*args[i]);
+ if (!arg) {
+ return nullptr;
+ }
+ stageArgs.push_back(std::move(arg));
+ }
+ size_t expectedArgs = 0;
+ // FIXME use a map
+ if ("premul" == name) {
+ stage = SkRasterPipeline::premul;
+ }
+ else if ("unpremul" == name) {
+ stage = SkRasterPipeline::unpremul;
+ }
+ else if ("clamp_0" == name) {
+ stage = SkRasterPipeline::clamp_0;
+ }
+ else if ("clamp_1" == name) {
+ stage = SkRasterPipeline::clamp_1;
+ }
+ else if ("matrix_4x5" == name) {
+ expectedArgs = 1;
+ stage = SkRasterPipeline::matrix_4x5;
+ if (1 == stageArgs.size() && stageArgs[0]->fType.fName != "float[20]") {
+ fErrors.error(offset, "pipeline stage '" + name + "' expected a float[20] argument");
+ return nullptr;
+ }
+ }
+ else {
+ bool found = false;
+ for (const auto& e : *fProgramElements) {
+ if (ProgramElement::kFunction_Kind == e->fKind) {
+ const FunctionDefinition& f = (const FunctionDefinition&) *e;
+ if (f.fDeclaration.fName == name) {
+ stage = SkRasterPipeline::callback;
+ std::vector<const FunctionDeclaration*> functions = { &f.fDeclaration };
+ stageArgs.emplace_back(new FunctionReference(fContext, offset, functions));
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ fErrors.error(offset, "'" + name + "' is not a valid pipeline stage");
+ return nullptr;
+ }
+ }
+ if (args.size() != expectedArgs + 2) {
+ fErrors.error(offset, "pipeline stage '" + name + "' expected an additional argument " +
+ "count of " + to_string((int) expectedArgs) + ", but found " +
+ to_string((int) args.size() - 1));
+ return nullptr;
+ }
+ return std::unique_ptr<Expression>(new AppendStage(fContext, offset, stage,
+ std::move(stageArgs)));
+#else
+ ASSERT(false);
+ return nullptr;
+#endif
+}
+
std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
const ASTSuffixExpression& expression) {
std::unique_ptr<Expression> base = this->convertExpression(*expression.fBase);
@@ -1996,6 +2082,10 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
}
case ASTSuffix::kCall_Kind: {
auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArguments;
+ if (Expression::kFunctionReference_Kind == base->fKind &&
+ "append" == ((const FunctionReference&) *base).fFunctions[0]->fName) {
+ return convertAppend(expression.fOffset, *rawArguments);
+ }
std::vector<std::unique_ptr<Expression>> arguments;
for (size_t i = 0; i < rawArguments->size(); i++) {
std::unique_ptr<Expression> converted =