liyujie
2025-08-28 786ff4f4ca2374bdd9177f2e24b503d43e7a3b93
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
134
135
136
137
138
139
140
141
/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
 
#ifndef SKSL_CPPCODEGENERATOR
#define SKSL_CPPCODEGENERATOR
 
#include "SkSLGLSLCodeGenerator.h"
#include "SkSLSectionAndParameterHelper.h"
 
#include <set>
 
namespace SkSL {
 
class CPPCodeGenerator : public GLSLCodeGenerator {
public:
    CPPCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
                     String name, OutputStream* out);
 
    bool generateCode() override;
 
private:
    void writef(const char* s, va_list va) SKSL_PRINTF_LIKE(2, 0);
 
    void writef(const char* s, ...) SKSL_PRINTF_LIKE(2, 3);
 
    bool writeSection(const char* name, const char* prefix = "");
 
    void writeHeader() override;
 
    bool usesPrecisionModifiers() const override;
 
    String getTypeName(const Type& type) override;
 
    void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence) override;
 
    void writeIndexExpression(const IndexExpression& i) override;
 
    void writeIntLiteral(const IntLiteral& i) override;
 
    void writeSwizzle(const Swizzle& swizzle) override;
 
    void writeFieldAccess(const FieldAccess& access) override;
 
    void writeVariableReference(const VariableReference& ref) override;
 
    String getSamplerHandle(const Variable& var);
 
    void writeIfStatement(const IfStatement& s) override;
 
    void writeReturnStatement(const ReturnStatement& s) override;
 
    void writeSwitchStatement(const SwitchStatement& s) override;
 
    void writeFunctionCall(const FunctionCall& c) override;
 
    void writeFunction(const FunctionDefinition& f) override;
 
    void writeSetting(const Setting& s) override;
 
    void writeProgramElement(const ProgramElement& p) override;
 
    void addUniform(const Variable& var);
 
    // writes a printf escape that will be filled in at runtime by the given C++ expression string
    void writeRuntimeValue(const Type& type, const Layout& layout, const String& cppCode);
 
    void writeVarInitializer(const Variable& var, const Expression& value) override;
 
    void writeInputVars() override;
 
    void writePrivateVars();
 
    void writePrivateVarValues();
 
    void writeCodeAppend(const String& code);
 
    bool writeEmitCode(std::vector<const Variable*>& uniforms);
 
    void writeSetData(std::vector<const Variable*>& uniforms);
 
    void writeGetKey();
 
    void writeOnTextureSampler();
 
    void writeClone();
 
    void writeTest();
 
    // If the returned C++ is included in the generated code, then the variable name stored in
    // cppVar will refer to a valid SkString that matches the Expression. Successful returns leave
    // the output buffer (and related state) unmodified.
    //
    // In the simplest cases, this will return "SkString {cppVar}(\"{e}\");", while more advanced
    // cases will properly insert format arguments.
    String convertSKSLExpressionToCPP(const Expression& e, const String& cppVar);
 
    // Process accumulated sksl to split it into appended code sections, properly interleaved with
    // the extra emit code blocks, based on statement/block locations and the inserted tokens
    // from newExtraEmitCodeBlock(). It is necessary to split the sksl after the program has been
    // fully walked since many elements redirect fOut to simultaneously build header sections and
    // bodies that are then concatenated; due to this it is not possible to split the sksl emission
    // on the fly.
    void flushEmittedCode();
 
    // Start a new extra emit code block for accumulating C++ code. This will insert a token into
    // the sksl stream to mark the fence between previous complete sksl statements and where the
    // C++ code added to the new block will be added to emitCode(). These tokens are removed by
    // flushEmittedCode() as it consumes them before passing pure sksl to writeCodeAppend().
    void newExtraEmitCodeBlock();
 
    // Append CPP code to the current extra emit code block.
    void addExtraEmitCodeLine(const String& toAppend);
 
    int getChildFPIndex(const Variable& var) const;
 
    String fName;
    String fFullName;
    SectionAndParameterHelper fSectionAndParameterHelper;
    std::vector<String> fExtraEmitCodeBlocks;
 
    std::vector<String> fFormatArgs;
    std::set<int> fWrittenTransformedCoords;
    // if true, we are writing a C++ expression instead of a GLSL expression
    bool fCPPMode = false;
    bool fInMain = false;
 
    // if not null, we are accumulating SkSL for emitCode into fOut, which
    // replaced the original buffer with a StringStream. The original buffer is
    // stored here for restoration.
    OutputStream* fCPPBuffer = nullptr;
 
    typedef GLSLCodeGenerator INHERITED;
};
 
}
 
#endif