1 /*
2  * Copyright 2016 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 SKSL_INTERFACEBLOCK
9 #define SKSL_INTERFACEBLOCK
10 
11 #include "src/sksl/ir/SkSLProgramElement.h"
12 #include "src/sksl/ir/SkSLSymbolTable.h"
13 #include "src/sksl/ir/SkSLVarDeclarations.h"
14 
15 namespace SkSL {
16 
17 /**
18  * An interface block, as in:
19  *
20  * out sk_PerVertex {
21  *   layout(builtin=0) float4 sk_Position;
22  *   layout(builtin=1) float sk_PointSize;
23  * };
24  *
25  * At the IR level, this is represented by a single variable of struct type.
26  */
27 class InterfaceBlock final : public ProgramElement {
28 public:
29     static constexpr Kind kProgramElementKind = Kind::kInterfaceBlock;
30 
InterfaceBlock(int offset,const Variable * var,String typeName,String instanceName,ExpressionArray sizes,std::shared_ptr<SymbolTable> typeOwner)31     InterfaceBlock(int offset, const Variable* var, String typeName, String instanceName,
32                    ExpressionArray sizes, std::shared_ptr<SymbolTable> typeOwner)
33     : INHERITED(offset, kProgramElementKind)
34     , fVariable(var)
35     , fTypeName(std::move(typeName))
36     , fInstanceName(std::move(instanceName))
37     , fSizes(std::move(sizes))
38     , fTypeOwner(std::move(typeOwner)) {}
39 
variable()40     const Variable& variable() const {
41         return *fVariable;
42     }
43 
setVariable(const Variable * var)44     void setVariable(const Variable* var) {
45         fVariable = var;
46     }
47 
typeName()48     const String& typeName() const {
49         return fTypeName;
50     }
51 
instanceName()52     const String& instanceName() const {
53         return fInstanceName;
54     }
55 
typeOwner()56     const std::shared_ptr<SymbolTable>& typeOwner() const {
57         return fTypeOwner;
58     }
59 
sizes()60     ExpressionArray& sizes() {
61         return fSizes;
62     }
63 
sizes()64     const ExpressionArray& sizes() const {
65         return fSizes;
66     }
67 
clone()68     std::unique_ptr<ProgramElement> clone() const override {
69         ExpressionArray sizesClone;
70         sizesClone.reserve_back(this->sizes().size());
71         for (const auto& size : this->sizes()) {
72             sizesClone.push_back(size ? size->clone() : nullptr);
73         }
74         return std::make_unique<InterfaceBlock>(fOffset, &this->variable(), this->typeName(),
75                                                 this->instanceName(), std::move(sizesClone),
76                                                 SymbolTable::WrapIfBuiltin(this->typeOwner()));
77     }
78 
description()79     String description() const override {
80         String result = this->variable().modifiers().description() + this->typeName() + " {\n";
81         const Type* structType = &this->variable().type();
82         while (structType->typeKind() == Type::TypeKind::kArray) {
83             structType = &structType->componentType();
84         }
85         for (const auto& f : structType->fields()) {
86             result += f.description() + "\n";
87         }
88         result += "}";
89         if (this->instanceName().size()) {
90             result += " " + this->instanceName();
91             for (const auto& size : this->sizes()) {
92                 result += "[";
93                 if (size) {
94                     result += size->description();
95                 }
96                 result += "]";
97             }
98         }
99         return result + ";";
100     }
101 
102 private:
103     const Variable* fVariable;
104     String fTypeName;
105     String fInstanceName;
106     ExpressionArray fSizes;
107     std::shared_ptr<SymbolTable> fTypeOwner;
108 
109     using INHERITED = ProgramElement;
110 };
111 
112 }  // namespace SkSL
113 
114 #endif
115