/*
 * 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_PROGRAMSETTINGS
#define SKSL_PROGRAMSETTINGS

#include "include/sksl/SkSLVersion.h"
#include "src/sksl/SkSLDefines.h"
#include "src/sksl/SkSLProgramKind.h"

#include <vector>

namespace SkSL {

/**
 * Holds the compiler settings for a program.
 */
struct ProgramSettings {
    // If true, the destination fragment color can be read from sk_FragColor. It must be declared
    // inout. This is only supported in GLSL, when framebuffer-fetch is used.
    bool fFragColorIsInOut = false;
    // if true, all halfs are forced to be floats
    bool fForceHighPrecision = false;
    // if true, add -0.5 bias to LOD of all texture lookups
    bool fSharpenTextures = false;
    // If true, sk_FragCoord, the dFdy gradient, and sk_Clockwise won't be modified by the
    // rtFlip. Additionally, the 'fUseFlipRTUniform' boolean will be forced to false so no rtFlip
    // uniform will be emitted.
    bool fForceNoRTFlip = false;
    // if the program needs to create an RTFlip uniform, this is its offset in the uniform buffer
    int fRTFlipOffset = -1;
    // if the program needs to create an RTFlip uniform and is creating SPIR-V, this is the binding
    // and set number of the uniform buffer.
    int fRTFlipBinding = -1;
    int fRTFlipSet = -1;
    // If layout(set=S, binding=B) is not specified for a uniform, these values will be used.
    // At present, zero is always used by our backends.
    int fDefaultUniformSet = 0;
    int fDefaultUniformBinding = 0;
    // Enables the SkSL optimizer. Note that we never disable optimizations which are needed to
    // fully evaluate constant-expressions, like constant folding or constant-intrinsic evaluation.
    bool fOptimize = true;
    // (Requires fOptimize = true) Removes any uncalled functions other than main(). Note that a
    // function which starts out being used may end up being uncalled after optimization.
    bool fRemoveDeadFunctions = true;
    // (Requires fOptimize = true) Removes variables which are never used.
    bool fRemoveDeadVariables = true;
    // (Requires fOptimize = true) When greater than zero, enables the inliner. The threshold value
    // sets an upper limit on the acceptable amount of code growth from inlining.
    int fInlineThreshold = SkSL::kDefaultInlineThreshold;
    // If true, every function in the generated program will be given the `noinline` modifier.
    bool fForceNoInline = false;
    // If true, implicit conversions to lower precision numeric types are allowed (e.g., float to
    // half). These are always allowed when compiling Runtime Effects.
    bool fAllowNarrowingConversions = false;
    // If true, then Debug code will run SPIR-V output through the validator to ensure its
    // correctness
    bool fValidateSPIRV = true;
    // If true, any synthetic uniforms must use push constant syntax
    bool fUsePushConstants = false;
    // TODO(skia:11209) - Replace this with a "promised" capabilities?
    // Sets a maximum SkSL version. Compilation will fail if the program uses features that aren't
    // allowed at the requested version. For instance, a valid program must have fully-unrollable
    // `for` loops at version 100, but any loop structure is allowed at version 300.
    SkSL::Version fMaxVersionAllowed = SkSL::Version::k100;
    // If true, SkSL will use a memory pool for all IR nodes when compiling a program. This is
    // usually a significant speed increase, but uses more memory, so it is a good idea for programs
    // that will be freed shortly after compilation. It can also be useful to disable this flag when
    // investigating memory corruption. (This controls behavior of the SkSL compiler, not the code
    // we generate.)
    bool fUseMemoryPool = true;
    // If true, VarDeclaration can be cloned for testing purposes. See VarDeclaration::clone for
    // more information.
    bool fAllowVarDeclarationCloneForTesting = false;
};

/**
 * All the configuration data for a given program.
 */
struct ProgramConfig {
    /** True if we are currently processing one of the built-in SkSL include modules. */
    bool fIsBuiltinCode;
    ProgramKind fKind;
    ProgramSettings fSettings;

    // When enforcesSkSLVersion() is true, this determines the available feature set that will be
    // enforced. This is set automatically when the `#version` directive is parsed.
    SkSL::Version fRequiredSkSLVersion = SkSL::Version::k100;

    bool enforcesSkSLVersion() const {
        return IsRuntimeEffect(fKind);
    }

    bool strictES2Mode() const {
        // TODO(skia:11209): Remove the first condition - so this is just based on #version.
        //                   Make it more generic (eg, isVersionLT) checking.
        return fSettings.fMaxVersionAllowed == Version::k100 &&
               fRequiredSkSLVersion == Version::k100 &&
               this->enforcesSkSLVersion();
    }

    const char* versionDescription() const {
        if (this->enforcesSkSLVersion()) {
            switch (fRequiredSkSLVersion) {
                case Version::k100: return "#version 100\n";
                case Version::k300: return "#version 300\n";
            }
        }
        return "";
    }

    static bool IsFragment(ProgramKind kind) {
        return kind == ProgramKind::kFragment ||
               kind == ProgramKind::kGraphiteFragment;
    }

    static bool IsVertex(ProgramKind kind) {
        return kind == ProgramKind::kVertex ||
               kind == ProgramKind::kGraphiteVertex;
    }

    static bool IsCompute(ProgramKind kind) {
        return kind == ProgramKind::kCompute;
    }

    static bool IsRuntimeEffect(ProgramKind kind) {
        return (kind == ProgramKind::kRuntimeColorFilter ||
                kind == ProgramKind::kRuntimeShader ||
                kind == ProgramKind::kRuntimeBlender ||
                kind == ProgramKind::kPrivateRuntimeColorFilter ||
                kind == ProgramKind::kPrivateRuntimeShader ||
                kind == ProgramKind::kPrivateRuntimeBlender ||
                kind == ProgramKind::kMeshVertex ||
                kind == ProgramKind::kMeshFragment);
    }

    static bool IsRuntimeShader(ProgramKind kind) {
        return (kind == ProgramKind::kRuntimeShader ||
                kind == ProgramKind::kPrivateRuntimeShader);
    }

    static bool IsRuntimeColorFilter(ProgramKind kind) {
        return (kind == ProgramKind::kRuntimeColorFilter ||
                kind == ProgramKind::kPrivateRuntimeColorFilter);
    }

    static bool IsRuntimeBlender(ProgramKind kind) {
        return (kind == ProgramKind::kRuntimeBlender ||
                kind == ProgramKind::kPrivateRuntimeBlender);
    }

    static bool AllowsPrivateIdentifiers(ProgramKind kind) {
        return (kind != ProgramKind::kRuntimeColorFilter &&
                kind != ProgramKind::kRuntimeShader &&
                kind != ProgramKind::kRuntimeBlender &&
                kind != ProgramKind::kMeshVertex &&
                kind != ProgramKind::kMeshFragment);
    }
};

}  // namespace SkSL

#endif
