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