| /* |
| * Copyright 2016 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SKSL_LAYOUT |
| #define SKSL_LAYOUT |
| |
| #include "src/sksl/SkSLString.h" |
| #include "src/sksl/SkSLUtil.h" |
| |
| namespace SkSL { |
| |
| /** |
| * Represents a layout block appearing before a variable declaration, as in: |
| * |
| * layout (location = 0) int x; |
| */ |
| struct Layout { |
| enum Flag { |
| kOriginUpperLeft_Flag = 1 << 0, |
| kOverrideCoverage_Flag = 1 << 1, |
| kPushConstant_Flag = 1 << 2, |
| kBlendSupportAllEquations_Flag = 1 << 3, |
| kBlendSupportMultiply_Flag = 1 << 4, |
| kBlendSupportScreen_Flag = 1 << 5, |
| kBlendSupportOverlay_Flag = 1 << 6, |
| kBlendSupportDarken_Flag = 1 << 7, |
| kBlendSupportLighten_Flag = 1 << 8, |
| kBlendSupportColorDodge_Flag = 1 << 9, |
| kBlendSupportColorBurn_Flag = 1 << 10, |
| kBlendSupportHardLight_Flag = 1 << 11, |
| kBlendSupportSoftLight_Flag = 1 << 12, |
| kBlendSupportDifference_Flag = 1 << 13, |
| kBlendSupportExclusion_Flag = 1 << 14, |
| kBlendSupportHSLHue_Flag = 1 << 15, |
| kBlendSupportHSLSaturation_Flag = 1 << 16, |
| kBlendSupportHSLColor_Flag = 1 << 17, |
| kBlendSupportHSLLuminosity_Flag = 1 << 18, |
| kTracked_Flag = 1 << 19, |
| kSRGBUnpremul_Flag = 1 << 20, |
| }; |
| |
| enum Primitive { |
| kUnspecified_Primitive = -1, |
| kPoints_Primitive, |
| kLines_Primitive, |
| kLineStrip_Primitive, |
| kLinesAdjacency_Primitive, |
| kTriangles_Primitive, |
| kTriangleStrip_Primitive, |
| kTrianglesAdjacency_Primitive |
| }; |
| |
| // These are used by images in GLSL. We only support a subset of what GL supports. |
| enum class Format { |
| kUnspecified = -1, |
| kRGBA32F, |
| kR32F, |
| kRGBA16F, |
| kR16F, |
| kLUMINANCE16F, |
| kRGBA8, |
| kR8, |
| kRGBA8I, |
| kR8I, |
| kRG16F, |
| }; |
| |
| // used by SkSL processors |
| enum Key { |
| // field is not a key |
| kNo_Key, |
| // field is a key |
| kKey_Key, |
| // key is 0 or 1 depending on whether the matrix is an identity matrix |
| kIdentity_Key, |
| }; |
| |
| enum class CType { |
| kDefault, |
| kBool, |
| kFloat, |
| kFloat2, |
| kFloat3, |
| kFloat4, |
| kInt32, |
| kSkRect, |
| kSkIRect, |
| kSkPMColor4f, |
| kSkPMColor, |
| kSkV4, |
| kSkPoint, |
| kSkIPoint, |
| kSkMatrix, |
| kSkM44, |
| kGrSurfaceProxyView, |
| kGrFragmentProcessor, |
| }; |
| |
| static const char* FormatToStr(Format format) { |
| switch (format) { |
| case Format::kUnspecified: return ""; |
| case Format::kRGBA32F: return "rgba32f"; |
| case Format::kR32F: return "r32f"; |
| case Format::kRGBA16F: return "rgba16f"; |
| case Format::kR16F: return "r16f"; |
| case Format::kLUMINANCE16F: return "lum16f"; |
| case Format::kRGBA8: return "rgba8"; |
| case Format::kR8: return "r8"; |
| case Format::kRGBA8I: return "rgba8i"; |
| case Format::kR8I: return "r8i"; |
| case Format::kRG16F: return "rg16f"; |
| } |
| ABORT("Unexpected format"); |
| } |
| |
| static bool ReadFormat(String str, Format* format) { |
| if (str == "rgba32f") { |
| *format = Format::kRGBA32F; |
| return true; |
| } else if (str == "r32f") { |
| *format = Format::kR32F; |
| return true; |
| } else if (str == "rgba16f") { |
| *format = Format::kRGBA16F; |
| return true; |
| } else if (str == "r16f") { |
| *format = Format::kR16F; |
| return true; |
| } else if (str == "lum16f") { |
| *format = Format::kLUMINANCE16F; |
| return true; |
| } else if (str == "rgba8") { |
| *format = Format::kRGBA8; |
| return true; |
| } else if (str == "r8") { |
| *format = Format::kR8; |
| return true; |
| } else if (str == "rgba8i") { |
| *format = Format::kRGBA8I; |
| return true; |
| } else if (str == "r8i") { |
| *format = Format::kR8I; |
| return true; |
| } else if (str == "rg16f") { |
| *format = Format::kRG16F; |
| return true; |
| } |
| return false; |
| } |
| |
| static const char* CTypeToStr(CType ctype) { |
| switch (ctype) { |
| case CType::kDefault: |
| return nullptr; |
| case CType::kFloat: |
| return "float"; |
| case CType::kInt32: |
| return "int32_t"; |
| case CType::kSkRect: |
| return "SkRect"; |
| case CType::kSkIRect: |
| return "SkIRect"; |
| case CType::kSkPMColor4f: |
| return "SkPMColor4f"; |
| case CType::kSkPMColor: |
| return "SkPMColor"; |
| case CType::kSkV4: |
| return "SkV4"; |
| case CType::kSkPoint: |
| return "SkPoint"; |
| case CType::kSkIPoint: |
| return "SkIPoint"; |
| case CType::kSkMatrix: |
| return "SkMatrix"; |
| case CType::kSkM44: |
| return "SkM44"; |
| case CType::kGrSurfaceProxyView: |
| return "GrSurfaceProxyView"; |
| case CType::kGrFragmentProcessor: |
| return "std::unique_ptr<GrFragmentProcessor>"; |
| default: |
| SkASSERT(false); |
| return nullptr; |
| } |
| } |
| |
| Layout(int flags, int location, int offset, int binding, int index, int set, int builtin, |
| int inputAttachmentIndex, Format format, Primitive primitive, int maxVertices, |
| int invocations, StringFragment marker, StringFragment when, Key key, CType ctype) |
| : fFlags(flags) |
| , fLocation(location) |
| , fOffset(offset) |
| , fBinding(binding) |
| , fIndex(index) |
| , fSet(set) |
| , fBuiltin(builtin) |
| , fInputAttachmentIndex(inputAttachmentIndex) |
| , fFormat(format) |
| , fPrimitive(primitive) |
| , fMaxVertices(maxVertices) |
| , fInvocations(invocations) |
| , fMarker(marker) |
| , fWhen(when) |
| , fKey(key) |
| , fCType(ctype) {} |
| |
| Layout() |
| : fFlags(0) |
| , fLocation(-1) |
| , fOffset(-1) |
| , fBinding(-1) |
| , fIndex(-1) |
| , fSet(-1) |
| , fBuiltin(-1) |
| , fInputAttachmentIndex(-1) |
| , fFormat(Format::kUnspecified) |
| , fPrimitive(kUnspecified_Primitive) |
| , fMaxVertices(-1) |
| , fInvocations(-1) |
| , fKey(kNo_Key) |
| , fCType(CType::kDefault) {} |
| |
| String description() const { |
| String result; |
| auto separator = [firstSeparator = true]() mutable -> String { |
| if (firstSeparator) { |
| firstSeparator = false; |
| return ""; |
| } else { |
| return ", "; |
| }}; |
| if (fLocation >= 0) { |
| result += separator() + "location = " + to_string(fLocation); |
| } |
| if (fOffset >= 0) { |
| result += separator() + "offset = " + to_string(fOffset); |
| } |
| if (fBinding >= 0) { |
| result += separator() + "binding = " + to_string(fBinding); |
| } |
| if (fIndex >= 0) { |
| result += separator() + "index = " + to_string(fIndex); |
| } |
| if (fSet >= 0) { |
| result += separator() + "set = " + to_string(fSet); |
| } |
| if (fBuiltin >= 0) { |
| result += separator() + "builtin = " + to_string(fBuiltin); |
| } |
| if (fInputAttachmentIndex >= 0) { |
| result += separator() + "input_attachment_index = " + to_string(fInputAttachmentIndex); |
| } |
| if (Format::kUnspecified != fFormat) { |
| result += separator() + FormatToStr(fFormat); |
| } |
| if (fFlags & kOriginUpperLeft_Flag) { |
| result += separator() + "origin_upper_left"; |
| } |
| if (fFlags & kOverrideCoverage_Flag) { |
| result += separator() + "override_coverage"; |
| } |
| if (fFlags & kBlendSupportAllEquations_Flag) { |
| result += separator() + "blend_support_all_equations"; |
| } |
| if (fFlags & kBlendSupportMultiply_Flag) { |
| result += separator() + "blend_support_multiply"; |
| } |
| if (fFlags & kBlendSupportScreen_Flag) { |
| result += separator() + "blend_support_screen"; |
| } |
| if (fFlags & kBlendSupportOverlay_Flag) { |
| result += separator() + "blend_support_overlay"; |
| } |
| if (fFlags & kBlendSupportDarken_Flag) { |
| result += separator() + "blend_support_darken"; |
| } |
| if (fFlags & kBlendSupportLighten_Flag) { |
| result += separator() + "blend_support_lighten"; |
| } |
| if (fFlags & kBlendSupportColorDodge_Flag) { |
| result += separator() + "blend_support_colordodge"; |
| } |
| if (fFlags & kBlendSupportColorBurn_Flag) { |
| result += separator() + "blend_support_colorburn"; |
| } |
| if (fFlags & kBlendSupportHardLight_Flag) { |
| result += separator() + "blend_support_hardlight"; |
| } |
| if (fFlags & kBlendSupportSoftLight_Flag) { |
| result += separator() + "blend_support_softlight"; |
| } |
| if (fFlags & kBlendSupportDifference_Flag) { |
| result += separator() + "blend_support_difference"; |
| } |
| if (fFlags & kBlendSupportExclusion_Flag) { |
| result += separator() + "blend_support_exclusion"; |
| } |
| if (fFlags & kBlendSupportHSLHue_Flag) { |
| result += separator() + "blend_support_hsl_hue"; |
| } |
| if (fFlags & kBlendSupportHSLSaturation_Flag) { |
| result += separator() + "blend_support_hsl_saturation"; |
| } |
| if (fFlags & kBlendSupportHSLColor_Flag) { |
| result += separator() + "blend_support_hsl_color"; |
| } |
| if (fFlags & kBlendSupportHSLLuminosity_Flag) { |
| result += separator() + "blend_support_hsl_luminosity"; |
| } |
| if (fFlags & kPushConstant_Flag) { |
| result += separator() + "push_constant"; |
| } |
| if (fFlags & kTracked_Flag) { |
| result += separator() + "tracked"; |
| } |
| if (fFlags & kSRGBUnpremul_Flag) { |
| result += separator() + "srgb_unpremul"; |
| } |
| switch (fPrimitive) { |
| case kPoints_Primitive: |
| result += separator() + "points"; |
| break; |
| case kLines_Primitive: |
| result += separator() + "lines"; |
| break; |
| case kLineStrip_Primitive: |
| result += separator() + "line_strip"; |
| break; |
| case kLinesAdjacency_Primitive: |
| result += separator() + "lines_adjacency"; |
| break; |
| case kTriangles_Primitive: |
| result += separator() + "triangles"; |
| break; |
| case kTriangleStrip_Primitive: |
| result += separator() + "triangle_strip"; |
| break; |
| case kTrianglesAdjacency_Primitive: |
| result += separator() + "triangles_adjacency"; |
| break; |
| case kUnspecified_Primitive: |
| break; |
| } |
| if (fMaxVertices >= 0) { |
| result += separator() + "max_vertices = " + to_string(fMaxVertices); |
| } |
| if (fInvocations >= 0) { |
| result += separator() + "invocations = " + to_string(fInvocations); |
| } |
| if (fMarker.fLength) { |
| result += separator() + "marker = " + fMarker; |
| } |
| if (fWhen.fLength) { |
| result += separator() + "when = " + fWhen; |
| } |
| if (result.size() > 0) { |
| result = "layout (" + result + ")"; |
| } |
| if (fKey) { |
| result += "/* key */"; |
| } |
| return result; |
| } |
| |
| bool operator==(const Layout& other) const { |
| return fFlags == other.fFlags && |
| fLocation == other.fLocation && |
| fOffset == other.fOffset && |
| fBinding == other.fBinding && |
| fIndex == other.fIndex && |
| fSet == other.fSet && |
| fBuiltin == other.fBuiltin && |
| fInputAttachmentIndex == other.fInputAttachmentIndex && |
| fFormat == other.fFormat && |
| fPrimitive == other.fPrimitive && |
| fMaxVertices == other.fMaxVertices && |
| fInvocations == other.fInvocations && |
| fMarker == other.fMarker && |
| fWhen == other.fWhen && |
| fKey == other.fKey && |
| fCType == other.fCType; |
| } |
| |
| bool operator!=(const Layout& other) const { |
| return !(*this == other); |
| } |
| |
| int fFlags; |
| int fLocation; |
| int fOffset; |
| int fBinding; |
| int fIndex; |
| int fSet; |
| // builtin comes from SPIR-V and identifies which particular builtin value this object |
| // represents. |
| int fBuiltin; |
| // input_attachment_index comes from Vulkan/SPIR-V to connect a shader variable to the a |
| // corresponding attachment on the subpass in which the shader is being used. |
| int fInputAttachmentIndex; |
| Format fFormat; |
| Primitive fPrimitive; |
| int fMaxVertices; |
| int fInvocations; |
| // marker refers to matrices tagged on the SkCanvas with markCTM |
| StringFragment fMarker; |
| StringFragment fWhen; |
| Key fKey; |
| CType fCType; |
| }; |
| |
| } // namespace |
| |
| #endif |