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

#ifndef SKSL_PIPELINESTAGECODEGENERATOR
#define SKSL_PIPELINESTAGECODEGENERATOR

#include "include/core/SkTypes.h"

#include <string>

namespace SkSL {

struct Program;
class VarDeclaration;

namespace PipelineStage {
    class Callbacks {
    public:
        virtual ~Callbacks() = default;

        virtual std::string getMainName() { return "main"; }
        virtual std::string getMangledName(const char* name) { return name; }
        virtual void   defineFunction(const char* declaration, const char* body, bool isMain) = 0;
        virtual void   declareFunction(const char* declaration) = 0;
        virtual void   defineStruct(const char* definition) = 0;
        virtual void   declareGlobal(const char* declaration) = 0;

        virtual std::string declareUniform(const VarDeclaration*) = 0;
        virtual std::string sampleShader(int index, std::string coords) = 0;
        virtual std::string sampleColorFilter(int index, std::string color) = 0;
        virtual std::string sampleBlender(int index, std::string src, std::string dst) = 0;

        virtual std::string toLinearSrgb(std::string color) = 0;
        virtual std::string fromLinearSrgb(std::string color) = 0;
    };

    /*
     * Processes 'program' for use in a GrFragmentProcessor, or other context that wants SkSL-like
     * code as input. To support fragment processor usage, there are callbacks that allow elements
     * to be declared programmatically and to rename those elements (mangling to avoid collisions).
     *
     * - Any reference to the main coords builtin variable will be replaced with 'sampleCoords'.
     * - Any reference to the input color builtin variable will be replaced with 'inputColor'.
     * - Any reference to the dest color builtin variable will be replaced with 'destColor'.
     *   Dest-color is used in blend programs.
     * - Each uniform variable declaration triggers a call to 'declareUniform', which should emit
     *   the declaration, and return the (possibly different) name to use for the variable.
     * - Each function definition triggers a call to 'defineFunction', which should emit the
     *   definition, and return the (possibly different) name to use for calls to that function.
     * - Each invocation of sample() triggers a call to 'sampleChild', which should return the full
     *   text of the call expression.
     */
    void ConvertProgram(const Program& program,
                        const char* sampleCoords,
                        const char* inputColor,
                        const char* destColor,
                        Callbacks* callbacks);
}  // namespace PipelineStage

}  // namespace SkSL

#endif
