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