1/*
2 * Copyright 2020 Google LLC
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 "include/private/SkSLSampleUsage.h"
9
10#include "src/sksl/ir/SkSLBinaryExpression.h"
11#include "src/sksl/ir/SkSLConstructor.h"
12#include "src/sksl/ir/SkSLDoStatement.h"
13#include "src/sksl/ir/SkSLExpression.h"
14#include "src/sksl/ir/SkSLExpressionStatement.h"
15#include "src/sksl/ir/SkSLFieldAccess.h"
16#include "src/sksl/ir/SkSLForStatement.h"
17#include "src/sksl/ir/SkSLFunctionCall.h"
18#include "src/sksl/ir/SkSLIfStatement.h"
19#include "src/sksl/ir/SkSLIndexExpression.h"
20#include "src/sksl/ir/SkSLPostfixExpression.h"
21#include "src/sksl/ir/SkSLPrefixExpression.h"
22#include "src/sksl/ir/SkSLProgram.h"
23#include "src/sksl/ir/SkSLReturnStatement.h"
24#include "src/sksl/ir/SkSLSwitchStatement.h"
25#include "src/sksl/ir/SkSLSwizzle.h"
26#include "src/sksl/ir/SkSLTernaryExpression.h"
27#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
28#include "src/sksl/ir/SkSLVariable.h"
29#include "src/sksl/ir/SkSLWhileStatement.h"
30
31namespace SkSL {
32
33SampleUsage SampleUsage::merge(const SampleUsage& other) {
34 if (other.fExplicitCoords) { fExplicitCoords = true; }
35 if (other.fPassThrough) { fPassThrough = true; }
36 if (other.fHasPerspective) { fHasPerspective = true; }
37
38 if (other.fKind == Kind::kVariable) {
39 fKind = Kind::kVariable;
40 fExpression.clear();
41 } else if (other.fKind == Kind::kUniform) {
42 if (fKind == Kind::kUniform) {
43 if (fExpression != other.fExpression) {
44 fKind = Kind::kVariable;
45 fExpression.clear();
46 } else {
47 // Identical uniform expressions, so leave things as-is
48 }
49 } else if (fKind == Kind::kNone) {
50 fKind = Kind::kUniform;
51 fExpression = other.fExpression;
52 } else {
53 // We were already variable, so leave things as-is
54 SkASSERT(fKind == Kind::kVariable);
55 }
56 } else {
57 // other had no matrix information, so we're done
58 }
59
60 return *this;
61}
62
63std::string SampleUsage::constructor(std::string perspectiveExpression) const {
64 SkASSERT(this->hasMatrix() || perspectiveExpression.empty());
65 if (perspectiveExpression.empty()) {
66 perspectiveExpression = fHasPerspective ? "true" : "false";
67 }
68
69 // Check for special cases where we can use our factories:
70 if (!this->hasMatrix()) {
71 if (fExplicitCoords && !fPassThrough) {
72 return "SkSL::SampleUsage::Explicit()";
73 } else if (fPassThrough && !fExplicitCoords) {
74 return "SkSL::SampleUsage::PassThrough()";
75 }
76 }
77 if (!fExplicitCoords && !fPassThrough) {
78 if (fKind == Kind::kVariable) {
79 return "SkSL::SampleUsage::VariableMatrix(" + perspectiveExpression + ")";
80 } else if (fKind == Kind::kUniform) {
81 return "SkSL::SampleUsage::UniformMatrix(\"" + fExpression + "\", " +
82 perspectiveExpression + ")";
83 }
84 }
85
86 // For more complex scenarios (mixed sampling), fall back to our universal constructor
87 std::string result = "SkSL::SampleUsage(SkSL::SampleUsage::Kind::";
88 switch (fKind) {
89 case Kind::kNone: result += "kNone"; break;
90 case Kind::kUniform: result += "kUniform"; break;
91 case Kind::kVariable: result += "kVariable"; break;
92 }
93 result += ", \"";
94 result += fExpression;
95 result += "\", ";
96 result += perspectiveExpression;
97 result += ", ";
98 result += fExplicitCoords ? "true, " : "false, ";
99 result += fPassThrough ? "true)" : "false)";
100
101 return result;
102}
103
104} // namespace SkSL
105