1/*
2 * Copyright 2018 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#ifndef SkSLUniformCTypes_DEFINED
9#define SkSLUniformCTypes_DEFINED
10
11#include "src/sksl/SkSLContext.h"
12#include "src/sksl/SkSLString.h"
13#include "src/sksl/ir/SkSLType.h"
14#include "src/sksl/ir/SkSLVariable.h"
15
16namespace SkSL {
17
18// This uses templates to define dirtyExpression(), saveState() and setUniform(). Each template can
19// reference token names formatted ${name} that are replaced with the actual values passed into the
20// functions.
21//
22// dirtyExpression() and saveState() support the following tokens:
23// - ${newVar} replaced with value of newValueVarName (1st argument)
24// - ${oldVar} replaced with value of oldValueVarName (2nd argument)
25//
26// setUniform() supports these tokens:
27// - ${pdman} replaced with value of pdmanName (1st argument)
28// - ${uniform} replaced with value of uniformHandleName (2nd argument)
29// - ${var} replaced with value of valueVarName (3rd argument)
30//
31// All templates and C++ snippets should produce valid expressions, but do not need to include
32// semicolons or newlines, which will be handled by the code generation itself.
33class UniformCTypeMapper {
34public:
35 // Create a templated mapper that does not support state tracking
36 UniformCTypeMapper(Layout::CType ctype, const std::vector<String>& skslTypes,
37 const char* setUniformFormat)
38 : UniformCTypeMapper(ctype, skslTypes, setUniformFormat, false, "", "", "") { }
39
40 // Create a templated mapper that provides extra patterns for the state
41 // tracking expressions.
42 UniformCTypeMapper(Layout::CType ctype, const std::vector<String>& skslTypes,
43 const String& setUniformFormat, const String& defaultValue,
44 const String& dirtyExpressionFormat, const String& saveStateFormat)
45 : UniformCTypeMapper(ctype, skslTypes, setUniformFormat,
46 true, defaultValue, dirtyExpressionFormat, saveStateFormat) { }
47
48 // Returns nullptr if the type and layout are not supported; the returned pointer's ownership
49 // is not transfered to the caller.
50 //
51 // The returned mapper can support tracking even if tracking is disabled based on the flags in
52 // the layout.
53 static const UniformCTypeMapper* Get(const Context& context, const Type& type,
54 const Layout& layout);
55
56 static const UniformCTypeMapper* Get(const Context& context, const Variable& variable) {
57 return Get(context, variable.fType, variable.fModifiers.fLayout);
58 }
59
60 // The C++ type name that this mapper applies to
61 Layout::CType ctype() const {
62 return fCType;
63 }
64
65 // The sksl type names that the mapper's ctype can be mapped to
66 const std::vector<String>& supportedTypeNames() const {
67 return fSKSLTypes;
68 }
69
70 // Whether or not this handler knows how to write state tracking code
71 // for the uniform variables
72 bool supportsTracking() const {
73 return fSupportsTracking;
74 }
75
76 // What the C++ class fields are initialized to in the GLSLFragmentProcessor The empty string
77 // implies the no-arg constructor is suitable. This is not used if supportsTracking() returns
78 // false.
79 //
80 // The returned snippet will be a valid as the lhs of an assignment.
81 const String& defaultValue() const {
82 return fDefaultValue;
83 }
84
85 // Return a boolean expression that returns true if the variables specified by newValueVarName
86 // and oldValueVarName have different values. This is ignored if supportsTracking() returns
87 // false.
88 //
89 // The returned snippet will be a valid expression to be inserted into the condition of an 'if'
90 // statement.
91 String dirtyExpression(const String& newValueVarName, const String& oldValueVarName) const;
92
93 // Return a statement that stores the value of newValueVarName into the variable specified by
94 // oldValueVarName. This is ignored if supportsTracking() returns false.
95 //
96 // The returned snippet will be a valid expression.
97 String saveState(const String& newValueVarName, const String& oldValueVarName) const;
98
99 // Return a statement that invokes the appropriate setX method on the GrGLSLProgramDataManager
100 // specified by pdmanName, where the uniform is provided by the expression stored in
101 // uniformHandleName, and valueVarName is the variable name pointing to the ctype instance
102 // holding the new value.
103 //
104 // The returned snippet will be a valid expression.
105 String setUniform(const String& pdmanName, const String& uniformHandleName,
106 const String& valueVarName) const;
107
108 // True if the setUniform() template only uses the value variable once in its expression. The
109 // variable does not necessarily get inlined if this returns true, since a local variable may be
110 // needed if state tracking is employed for a particular uniform.
111 bool canInlineUniformValue() const {
112 return fInlineValue;
113 }
114
115private:
116 UniformCTypeMapper(Layout::CType ctype, const std::vector<String>& skslTypes,
117 const String& setUniformFormat, bool enableTracking, const String& defaultValue,
118 const String& dirtyExpressionFormat, const String& saveStateFormat);
119
120 Layout::CType fCType;
121 std::vector<String> fSKSLTypes;
122 String fUniformTemplate;
123 bool fInlineValue; // Cached value calculated from fUniformTemplate
124
125 bool fSupportsTracking;
126 String fDefaultValue;
127 String fDirtyExpressionTemplate;
128 String fSaveStateTemplate;
129};
130
131} // namespace
132
133#endif // SkSLUniformCTypes_DEFINED
134