• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_MODIFIERS
9 #define SKSL_MODIFIERS
10 
11 #include "include/private/SkSLLayout.h"
12 
13 #include <cstddef>
14 #include <memory>
15 #include <string>
16 
17 namespace SkSL {
18 
19 class Context;
20 class Position;
21 
22 /**
23  * A set of modifier keywords (in, out, uniform, etc.) appearing before a declaration.
24  */
25 struct Modifiers {
26     /**
27      * OpenGL requires modifiers to be in a strict order:
28      * - invariant-qualifier:     (invariant)
29      * - interpolation-qualifier: flat, noperspective, (smooth)
30      * - storage-qualifier:       const, uniform
31      * - parameter-qualifier:     in, out, inout
32      * - precision-qualifier:     highp, mediump, lowp
33      *
34      * SkSL does not have `invariant` or `smooth`.
35      */
36 
37     enum Flag {
38         kNo_Flag             =       0,
39         // Real GLSL modifiers
40         kFlat_Flag           = 1 <<  0,
41         kNoPerspective_Flag  = 1 <<  1,
42         kConst_Flag          = 1 <<  2,
43         kUniform_Flag        = 1 <<  3,
44         kIn_Flag             = 1 <<  4,
45         kOut_Flag            = 1 <<  5,
46         kHighp_Flag          = 1 <<  6,
47         kMediump_Flag        = 1 <<  7,
48         kLowp_Flag           = 1 <<  8,
49         kReadOnly_Flag       = 1 <<  9,
50         kWriteOnly_Flag      = 1 << 10,
51         kBuffer_Flag         = 1 << 11,
52         // Corresponds to the GLSL 'shared' modifier. Only allowed in a compute program.
53         kWorkgroup_Flag      = 1 << 12,
54         // SkSL extensions, not present in GLSL
55         kExport_Flag         = 1 << 13,
56         kES3_Flag            = 1 << 14,
57         kPure_Flag           = 1 << 15,
58         kInline_Flag         = 1 << 16,
59         kNoInline_Flag       = 1 << 17,
60     };
61 
ModifiersModifiers62     Modifiers()
63     : fLayout(Layout())
64     , fFlags(0) {}
65 
ModifiersModifiers66     Modifiers(const Layout& layout, int flags)
67     : fLayout(layout)
68     , fFlags(flags) {}
69 
descriptionModifiers70     std::string description() const {
71         return fLayout.description() + DescribeFlags(fFlags) + " ";
72     }
73 
DescribeFlagsModifiers74     static std::string DescribeFlags(int flags) {
75         // SkSL extensions
76         std::string result;
77         if (flags & kExport_Flag) {
78             result += "$export ";
79         }
80         if (flags & kES3_Flag) {
81             result += "$es3 ";
82         }
83         if (flags & kPure_Flag) {
84             result += "$pure ";
85         }
86         if (flags & kInline_Flag) {
87             result += "inline ";
88         }
89         if (flags & kNoInline_Flag) {
90             result += "noinline ";
91         }
92 
93         // Real GLSL qualifiers (must be specified in order in GLSL 4.1 and below)
94         if (flags & kFlat_Flag) {
95             result += "flat ";
96         }
97         if (flags & kNoPerspective_Flag) {
98             result += "noperspective ";
99         }
100         if (flags & kConst_Flag) {
101             result += "const ";
102         }
103         if (flags & kUniform_Flag) {
104             result += "uniform ";
105         }
106         if ((flags & kIn_Flag) && (flags & kOut_Flag)) {
107             result += "inout ";
108         } else if (flags & kIn_Flag) {
109             result += "in ";
110         } else if (flags & kOut_Flag) {
111             result += "out ";
112         }
113         if (flags & kHighp_Flag) {
114             result += "highp ";
115         }
116         if (flags & kMediump_Flag) {
117             result += "mediump ";
118         }
119         if (flags & kLowp_Flag) {
120             result += "lowp ";
121         }
122         if (flags & kReadOnly_Flag) {
123             result += "readonly ";
124         }
125         if (flags & kWriteOnly_Flag) {
126             result += "writeonly ";
127         }
128         if (flags & kBuffer_Flag) {
129             result += "buffer ";
130         }
131 
132         // We're using a non-GLSL name for this one; the GLSL equivalent is "shared"
133         if (flags & kWorkgroup_Flag) {
134             result += "workgroup ";
135         }
136 
137         if (!result.empty()) {
138             result.pop_back();
139         }
140         return result;
141     }
142 
143     bool operator==(const Modifiers& other) const {
144         return fLayout == other.fLayout && fFlags == other.fFlags;
145     }
146 
147     bool operator!=(const Modifiers& other) const {
148         return !(*this == other);
149     }
150 
151     /**
152      * Verifies that only permitted modifiers and layout flags are included. Reports errors and
153      * returns false in the event of a violation.
154      */
155     bool checkPermitted(const Context& context,
156                         Position pos,
157                         int permittedModifierFlags,
158                         int permittedLayoutFlags) const;
159 
160     Layout fLayout;
161     int fFlags;
162 };
163 
164 } // namespace SkSL
165 
166 namespace std {
167 
168 template <>
169 struct hash<SkSL::Modifiers> {
170     size_t operator()(const SkSL::Modifiers& key) const {
171         return (size_t) key.fFlags ^ ((size_t) key.fLayout.fFlags << 8) ^
172                ((size_t) key.fLayout.fBuiltin << 16);
173     }
174 };
175 
176 } // namespace std
177 
178 #endif
179