| /* |
| * Copyright 2021 Google LLC. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "src/sksl/ir/SkSLModifierFlags.h" |
| |
| #include "include/core/SkTypes.h" |
| #include "src/sksl/SkSLContext.h" |
| #include "src/sksl/SkSLErrorReporter.h" |
| #include "src/sksl/SkSLPosition.h" |
| |
| namespace SkSL { |
| |
| std::string ModifierFlags::paddedDescription() const { |
| // SkSL extensions |
| std::string result; |
| if (*this & ModifierFlag::kExport) { |
| result += "$export "; |
| } |
| if (*this & ModifierFlag::kES3) { |
| result += "$es3 "; |
| } |
| if (*this & ModifierFlag::kPure) { |
| result += "$pure "; |
| } |
| if (*this & ModifierFlag::kInline) { |
| result += "inline "; |
| } |
| if (*this & ModifierFlag::kNoInline) { |
| result += "noinline "; |
| } |
| |
| // Real GLSL qualifiers (must be specified in order in GLSL 4.1 and below) |
| if (*this & ModifierFlag::kFlat) { |
| result += "flat "; |
| } |
| if (*this & ModifierFlag::kNoPerspective) { |
| result += "noperspective "; |
| } |
| if (*this & ModifierFlag::kConst) { |
| result += "const "; |
| } |
| if (*this & ModifierFlag::kUniform) { |
| result += "uniform "; |
| } |
| if ((*this & ModifierFlag::kIn) && (*this & ModifierFlag::kOut)) { |
| result += "inout "; |
| } else if (*this & ModifierFlag::kIn) { |
| result += "in "; |
| } else if (*this & ModifierFlag::kOut) { |
| result += "out "; |
| } |
| if (*this & ModifierFlag::kHighp) { |
| result += "highp "; |
| } |
| if (*this & ModifierFlag::kMediump) { |
| result += "mediump "; |
| } |
| if (*this & ModifierFlag::kLowp) { |
| result += "lowp "; |
| } |
| if (*this & ModifierFlag::kReadOnly) { |
| result += "readonly "; |
| } |
| if (*this & ModifierFlag::kWriteOnly) { |
| result += "writeonly "; |
| } |
| if (*this & ModifierFlag::kBuffer) { |
| result += "buffer "; |
| } |
| |
| // We're using non-GLSL names for these. |
| if (*this & ModifierFlag::kPixelLocal) { |
| // Roughly equivalent to `__pixel_localEXT`. |
| result += "pixel_local "; |
| } |
| if (*this & ModifierFlag::kWorkgroup) { |
| // Equivalent to `shared`. |
| result += "workgroup "; |
| } |
| |
| return result; |
| } |
| |
| std::string ModifierFlags::description() const { |
| std::string s = this->paddedDescription(); |
| if (!s.empty()) { |
| s.pop_back(); |
| } |
| return s; |
| } |
| |
| bool ModifierFlags::checkPermittedFlags(const Context& context, |
| Position pos, |
| ModifierFlags permittedModifierFlags) const { |
| static constexpr struct { ModifierFlag flag; const char* name; } kModifierFlags[] = { |
| { ModifierFlag::kConst, "const" }, |
| { ModifierFlag::kIn, "in" }, |
| { ModifierFlag::kOut, "out" }, |
| { ModifierFlag::kUniform, "uniform" }, |
| { ModifierFlag::kFlat, "flat" }, |
| { ModifierFlag::kNoPerspective, "noperspective" }, |
| { ModifierFlag::kPure, "$pure" }, |
| { ModifierFlag::kInline, "inline" }, |
| { ModifierFlag::kNoInline, "noinline" }, |
| { ModifierFlag::kHighp, "highp" }, |
| { ModifierFlag::kMediump, "mediump" }, |
| { ModifierFlag::kLowp, "lowp" }, |
| { ModifierFlag::kExport, "$export" }, |
| { ModifierFlag::kES3, "$es3" }, |
| { ModifierFlag::kWorkgroup, "workgroup" }, |
| { ModifierFlag::kReadOnly, "readonly" }, |
| { ModifierFlag::kWriteOnly, "writeonly" }, |
| { ModifierFlag::kBuffer, "buffer" }, |
| { ModifierFlag::kPixelLocal, "pixel_local" }, |
| }; |
| |
| bool success = true; |
| ModifierFlags modifierFlags = *this; |
| for (const auto& f : kModifierFlags) { |
| if (modifierFlags & f.flag) { |
| if (!(permittedModifierFlags & f.flag)) { |
| context.fErrors->error(pos, "'" + std::string(f.name) + "' is not permitted here"); |
| success = false; |
| } |
| modifierFlags &= ~f.flag; |
| } |
| } |
| SkASSERT(modifierFlags == ModifierFlag::kNone); |
| |
| return success; |
| } |
| |
| } // namespace SkSL |