/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrSkSLFP_DEFINED
#define GrSkSLFP_DEFINED

#include "include/core/SkRefCnt.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrCoordTransform.h"
#include "src/gpu/GrFragmentProcessor.h"
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/GrSkSLFPFactoryCache.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLPipelineStageCodeGenerator.h"
#include <atomic>

#if GR_TEST_UTILS
#define GR_FP_SRC_STRING const char*
#else
#define GR_FP_SRC_STRING static const char*
#endif

class GrContext_Base;
class GrSkSLFPFactory;

class GrSkSLFP : public GrFragmentProcessor {
public:
    /**
     * Returns a new unique identifier. Each different SkSL fragment processor should call
     * NewIndex once, statically, and use this index for all calls to Make.
     */
    static int NewIndex() {
        static std::atomic<int> nextIndex{0};
        return nextIndex++;
    }

    /**
     * Creates a new fragment processor from an SkSL source string and a struct of inputs to the
     * program. The input struct's type is derived from the 'in' and 'uniform' variables in the SkSL
     * source, so e.g. the shader:
     *
     *    in bool dither;
     *    uniform float x;
     *    uniform float y;
     *    ....
     *
     * would expect a pointer to a struct set up like:
     *
     * struct {
     *     bool dither;
     *     float x;
     *     float y;
     * };
     *
     * While both 'in' and 'uniform' variables go into this struct, the difference between them is
     * that 'in' variables are statically "baked in" to the generated code, becoming literals,
     * whereas uniform variables may be changed from invocation to invocation without having to
     * recompile the shader.
     *
     * As the decision of whether to create a new shader or just upload new uniforms all happens
     * behind the scenes, the difference between the two from an end-user perspective is primarily
     * in performance: on the one hand, changing the value of an 'in' variable is very expensive
     * (requiring the compiler to regenerate the code, upload a new shader to the GPU, and so
     * forth), but on the other hand the compiler can optimize around its value because it is known
     * at compile time. 'in' variables are therefore suitable for things like flags, where there are
     * only a few possible values and a known-in-advance value can cause entire chunks of code to
     * become dead (think static @ifs), while 'uniform's are used for continuous values like colors
     * and coordinates, where it would be silly to create a separate shader for each possible set of
     * values. Other than the (significant) performance implications, the only difference between
     * the two is that 'in' variables can be used in static @if / @switch tests. When in doubt, use
     * 'uniform'.
     *
     * As turning SkSL into GLSL / SPIR-V / etc. is fairly expensive, and the output may differ
     * based on the inputs, internally the process is divided into two steps: we first parse and
     * semantically analyze the SkSL into an internal representation, and then "specialize" this
     * internal representation based on the inputs. The unspecialized internal representation of
     * the program is cached, so further specializations of the same code are much faster than the
     * first call.
     *
     * This caching is based on the 'index' parameter, which should be derived by statically calling
     * 'NewIndex()'. Each given SkSL string should have a single, statically defined index
     * associated with it.
     */
    static std::unique_ptr<GrSkSLFP> Make(
                   GrContext_Base* context,
                   int index,
                   const char* name,
                   const char* sksl,
                   const void* inputs,
                   size_t inputSize,
                   SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind,
                   const SkMatrix* matrix = nullptr);

    static std::unique_ptr<GrSkSLFP> Make(
                   GrContext_Base* context,
                   int index,
                   const char* name,
                   SkString sksl,
                   const void* inputs,
                   size_t inputSize,
                   SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind,
                   const SkMatrix* matrix = nullptr);

    const char* name() const override;

    void addChild(std::unique_ptr<GrFragmentProcessor> child);

    std::unique_ptr<GrFragmentProcessor> clone() const override;

private:
    GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps,
             SkSL::Program::Kind kind, int fIndex, const char* name, const char* sksl,
             SkString skslString, const void* inputs, size_t inputSize, const SkMatrix* matrix);

    GrSkSLFP(const GrSkSLFP& other);

    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;

    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;

    bool onIsEqual(const GrFragmentProcessor&) const override;

    void createFactory() const;

    sk_sp<GrSkSLFPFactoryCache> fFactoryCache;

    const sk_sp<GrShaderCaps> fShaderCaps;

    mutable sk_sp<GrSkSLFPFactory> fFactory;

    SkSL::Program::Kind fKind;

    int fIndex;

    const char* fName;

    // For object lifetime purposes, we have fields for the SkSL as both a const char* and a
    // SkString. The const char* is the one we actually use, but it may point to the SkString's
    // bytes. Since GrSkSLFPs are frequently created from constant strings, this allows us to
    // generally avoid the overhead of copying the bytes into an SkString (in which case fSkSLString
    // is the empty string), while still allowing the GrSkSLFP to manage the string's lifetime when
    // needed.
    SkString fSkSLString;

    const char* fSkSL;

    const std::unique_ptr<int8_t[]> fInputs;

    size_t fInputSize;

    GrCoordTransform fCoordTransform;

    mutable SkSL::String fKey;

    GR_DECLARE_FRAGMENT_PROCESSOR_TEST

    typedef GrFragmentProcessor INHERITED;

    friend class GrGLSLSkSLFP;

    friend class GrSkSLFPFactory;
};

/**
 * Produces GrFragmentProcessors from SkSL code. As the shader code produced from the SkSL depends
 * upon the inputs to the SkSL (static if's, etc.) we first create a factory for a given SkSL
 * string, then use that to create the actual GrFragmentProcessor.
 */
class GrSkSLFPFactory : public SkNVRefCnt<GrSkSLFPFactory> {
public:
    /**
     * Constructs a GrSkSLFPFactory for a given SkSL source string. Creating a factory will
     * preprocess the SkSL and determine which of its inputs are declared "key" (meaning they cause
     * the produced shaders to differ), so it is important to reuse the same factory instance for
     * the same shader in order to avoid repeatedly re-parsing the SkSL.
     */
    GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl,
                    SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind);

    const SkSL::Program* getSpecialization(const SkSL::String& key, const void* inputs,
                                           size_t inputSize);

    SkSL::Program::Kind fKind;

    const char* fName;

    SkSL::Compiler fCompiler;

    std::shared_ptr<SkSL::Program> fBaseProgram;

    std::vector<const SkSL::Variable*> fInAndUniformVars;

    std::unordered_map<SkSL::String, std::unique_ptr<const SkSL::Program>> fSpecializations;

    friend class GrSkSLFP;
};

#endif
