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

#include "tests/Test.h"

#if defined(SK_GRAPHITE)

#include "include/core/SkColorSpace.h"
#include "include/effects/SkRuntimeEffect.h"
#include "include/gpu/graphite/precompile/PrecompileBlender.h"
#include "include/gpu/graphite/precompile/PrecompileColorFilter.h"
#include "include/gpu/graphite/precompile/PrecompileShader.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/FactoryFunctions.h"
#include "src/gpu/graphite/KeyContext.h"
#include "src/gpu/graphite/PipelineData.h"
#include "src/gpu/graphite/PrecompileInternal.h"
#include "src/gpu/graphite/Renderer.h"
#include "src/gpu/graphite/RuntimeEffectDictionary.h"
#include "src/gpu/graphite/precompile/PaintOptionsPriv.h"

#include <array>

using namespace::skgpu::graphite;

namespace {

// colorfilters
static constexpr int kExpectedBlendCFCombos = 1;
static constexpr int kExpectedColorSpaceCFCombos = 1;
static constexpr int kExpectedHighContrastCFCombos = 1;
static constexpr int kExpectedLightingCFCombos = 1;
static constexpr int kExpectedLumaCFCombos = 1;
static constexpr int kExpectedMatrixCFCombos = 1;
static constexpr int kExpectedOverdrawCFCombos = 1;
static constexpr int kExpectedTableCFCombos = 1;

// shaders
static constexpr int kExpectedGradientCombos = 3;
static constexpr int kExpectedImageCombos = 6;
static constexpr int kExpectedPerlinNoiseCombos = 1;
static constexpr int kExpectedPictureCombos = 12;
static constexpr int kExpectedRawImageCombos = 3;
static constexpr int kExpectedSolidColorCombos = 1;


// A default kSrcOver blend mode will be supplied if no other blend options are added
void no_blend_mode_option_test(const KeyContext& keyContext,
                               PipelineDataGatherer* gatherer,
                               skiatest::Reporter* reporter) {
    PaintOptions paintOptions;
    paintOptions.setShaders({ PrecompileShaders::Color() });

    REPORTER_ASSERT(reporter, paintOptions.priv().numCombinations() == 1);

    std::vector<UniquePaintParamsID> precompileIDs;
    paintOptions.priv().buildCombinations(keyContext,
                                          gatherer,
                                          DrawTypeFlags::kNone,
                                          /* withPrimitiveBlender= */ false,
                                          Coverage::kNone,
                                          [&precompileIDs](UniquePaintParamsID id,
                                                           DrawTypeFlags,
                                                           bool /* withPrimitiveBlender */,
                                                           Coverage) {
                                                               precompileIDs.push_back(id);
                                                           });

    SkASSERT(precompileIDs.size() == 1);
}

// This test checks that the 'PaintOptions::numCombinations' method and the number actually
// generated by 'buildCombinations' agree with the expected number of combinations.
void run_test(const KeyContext& keyContext,
              PipelineDataGatherer* gatherer,
              skiatest::Reporter* reporter,
              const PaintOptions& paintOptions,
              int expectedNumOptions) {

    REPORTER_ASSERT(reporter, paintOptions.priv().numCombinations() == expectedNumOptions);

    std::vector<UniquePaintParamsID> precompileIDs;
    paintOptions.priv().buildCombinations(keyContext,
                                          gatherer,
                                          DrawTypeFlags::kNone,
                                          /* withPrimitiveBlender= */ false,
                                          Coverage::kNone,
                                          [&precompileIDs](UniquePaintParamsID id,
                                                           DrawTypeFlags,
                                                           bool /* withPrimitiveBlender */,
                                                           Coverage) {
                                              precompileIDs.push_back(id);
                                          });

    SkASSERT(static_cast<int>(precompileIDs.size()) == expectedNumOptions);
}

void big_test(const KeyContext& keyContext,
              PipelineDataGatherer* gatherer,
              skiatest::Reporter* reporter) {

    static constexpr int kNumExpected = 444;
    // paintOptions (444 = 4*111)
    //  |- (111 = 3+108) sweepGrad_0 (3) |
    //  |                blendShader_0 (108 = 1*4*27)
    //  |                 |- 0: (1)       kSrc (1)
    //  |                 |- 1: (4=3+1)   (dsts) linearGrad_0 (3) | solid_0 (1)
    //  |                 |- 2: (27=3+24) (srcs) linearGrad_1 (3) |
    //  |                                        blendShader_1 (24=1*4*6)
    //  |                                         |- 0: (1) kDst (1)
    //  |                                         |- 1: (4=3+1) (dsts) radGrad_0 (3) | solid_1 (1)
    //  |                                         |- 2: (6) (srcs) imageShader_0 (6)
    //  |
    //  |- (4) 4-built-in-blend-modes

    PaintOptions paintOptions;

    // first, shaders. First top-level option (sweepGrad_0)
    sk_sp<PrecompileShader> sweepGrad_0 = PrecompileShaders::SweepGradient();

    std::array<SkBlendMode, 1> blendModes{ SkBlendMode::kSrc };

    std::vector<SkBlendMode> moreBlendModes{ SkBlendMode::kDst };

    // Second top-level option (blendShader_0)
    auto blendShader_0 = PrecompileShaders::Blend(
                                SkSpan<const SkBlendMode>(blendModes),          // std::array
                                {                                               // initializer_list
                                    PrecompileShaders::LinearGradient(),
                                    PrecompileShaders::Color()
                                },
                                {
                                    PrecompileShaders::LinearGradient(),
                                    PrecompileShaders::Blend(
                                            SkSpan<const SkBlendMode>(moreBlendModes),// std::vector
                                            {
                                                PrecompileShaders::RadialGradient(),
                                                PrecompileShaders::Color()
                                            },
                                            {
                                                PrecompileShaders::Image()
                                            })
                                });

    paintOptions.setShaders({ sweepGrad_0, blendShader_0 });

    static const SkBlendMode kEvenMoreBlendModes[] = {
        SkBlendMode::kSrcOver,
        SkBlendMode::kSrc,
        SkBlendMode::kDstOver,
        SkBlendMode::kDst
    };

    // now, blend modes
    paintOptions.setBlendModes(kEvenMoreBlendModes);                             // c array

    REPORTER_ASSERT(reporter, paintOptions.priv().numCombinations() == kNumExpected,
                    "Actual # of combinations %d", paintOptions.priv().numCombinations());

    std::vector<UniquePaintParamsID> precompileIDs;
    paintOptions.priv().buildCombinations(keyContext,
                                          gatherer,
                                          DrawTypeFlags::kNone,
                                          /* withPrimitiveBlender= */ false,
                                          Coverage::kNone,
                                          [&precompileIDs](UniquePaintParamsID id,
                                                           DrawTypeFlags,
                                                           bool /* withPrimitiveBlender */,
                                                           Coverage) {
                                                               precompileIDs.push_back(id);
                                                           });

    SkASSERT(precompileIDs.size() == kNumExpected);
}

template <typename T>
std::vector<sk_sp<T>> create_runtime_combos(
        skiatest::Reporter* reporter,
        SkRuntimeEffect::Result effectFactory(SkString),
        sk_sp<T> precompileFactory(sk_sp<SkRuntimeEffect>,
                                   SkSpan<const PrecompileChildOptions> childOptions),
        const char* redCode,
        const char* greenCode,
        const char* combineCode) {
    auto [redEffect, error1] = effectFactory(SkString(redCode));
    REPORTER_ASSERT(reporter, redEffect, "%s", error1.c_str());
    auto [greenEffect, error2] = effectFactory(SkString(greenCode));
    REPORTER_ASSERT(reporter, greenEffect, "%s", error2.c_str());
    auto [combineEffect, error3] = effectFactory(SkString(combineCode));
    REPORTER_ASSERT(reporter, combineEffect, "%s", error3.c_str());

    sk_sp<T> red = precompileFactory(redEffect, {});
    REPORTER_ASSERT(reporter, red);

    sk_sp<T> green = precompileFactory(greenEffect, {});
    REPORTER_ASSERT(reporter, green);

    sk_sp<T> combine = precompileFactory(combineEffect, { { red, green }, { green, red } });
    REPORTER_ASSERT(reporter, combine);

    return { combine };
}

void runtime_effect_test(const KeyContext& keyContext,
                         PipelineDataGatherer* gatherer,
                         skiatest::Reporter* reporter) {
    // paintOptions (8 = 2*2*2)
    //  |- combineShader (2)
    //  |       0: redShader   | greenShader
    //  |       1: greenShader | redShader
    //  |
    //  |- combineColorFilter (2)
    //  |       0: redColorFilter   | greenColorFilter
    //  |       1: greenColorFilter | redColorFilter
    //  |
    //  |- combineBlender (2)
    //  |       0: redBlender   | greenBlender
    //  |       1: greenBlender | redBlender

    PaintOptions paintOptions;

    // shaders
    {
        static const char* kRedS = R"(
            half4 main(vec2 fragcoord) { return half4(.5, 0, 0, .5); }
        )";
        static const char* kGreenS = R"(
            half4 main(vec2 fragcoord) { return half4(0, .5, 0, .5); }
        )";

        static const char* kCombineS = R"(
            uniform shader first;
            uniform shader second;
            half4 main(vec2 fragcoords) {
                return first.eval(fragcoords) + second.eval(fragcoords);
            }
        )";

        std::vector<sk_sp<PrecompileShader>> combinations =
                create_runtime_combos<PrecompileShader>(reporter,
                                                        SkRuntimeEffect::MakeForShader,
                                                        MakePrecompileShader,
                                                        kRedS,
                                                        kGreenS,
                                                        kCombineS);
        paintOptions.setShaders(combinations);
    }

    // color filters
    {
        static const char* kRedCF = R"(
            half4 main(half4 color) { return half4(.5, 0, 0, .5); }
        )";
        static const char* kGreenCF = R"(
            half4 main(half4 color) { return half4(0, .5, 0, .5); }
        )";

        static const char* kCombineCF = R"(
            uniform colorFilter first;
            uniform colorFilter second;
            half4 main(half4 color) { return first.eval(color) + second.eval(color); }
        )";

        std::vector<sk_sp<PrecompileColorFilter>> combinations =
                create_runtime_combos<PrecompileColorFilter>(reporter,
                                                             SkRuntimeEffect::MakeForColorFilter,
                                                             MakePrecompileColorFilter,
                                                             kRedCF,
                                                             kGreenCF,
                                                             kCombineCF);
        paintOptions.setColorFilters(combinations);
    }

    // blenders
    {
        static const char* kRedB = R"(
            half4 main(half4 src, half4 dst) { return half4(.5, 0, 0, .5); }
        )";
        static const char* kGreenB = R"(
            half4 main(half4 src, half4 dst) { return half4(0, .5, 0, .5); }
        )";

        static const char* kCombineB = R"(
            uniform blender first;
            uniform blender second;
            half4 main(half4 src, half4 dst) {
                return first.eval(src, dst) + second.eval(src, dst);
            }
        )";

        std::vector<sk_sp<PrecompileBlender>> combinations =
                create_runtime_combos<PrecompileBlender>(reporter,
                                                         SkRuntimeEffect::MakeForBlender,
                                                         MakePrecompileBlender,
                                                         kRedB,
                                                         kGreenB,
                                                         kCombineB);
        paintOptions.setBlenders(combinations);
    }

    REPORTER_ASSERT(reporter, paintOptions.priv().numCombinations() == 8);

    std::vector<UniquePaintParamsID> precompileIDs;
    paintOptions.priv().buildCombinations(keyContext,
                                          gatherer,
                                          DrawTypeFlags::kNone,
                                          /* withPrimitiveBlender= */ false,
                                          Coverage::kNone,
                                          [&precompileIDs](UniquePaintParamsID id,
                                                           DrawTypeFlags,
                                                           bool /* withPrimitiveBlender */,
                                                           Coverage) {
                                                               precompileIDs.push_back(id);
                                                           });

    SkASSERT(precompileIDs.size() == 8);
}

// Exercise all the PrecompileBlenders factories
void blend_subtest(const KeyContext& keyContext,
                   PipelineDataGatherer* gatherer,
                   skiatest::Reporter* reporter) {
    // The BlendMode PrecompileBlender only ever has 1 combination
    {
        PaintOptions paintOptions;
        paintOptions.setBlenders({ PrecompileBlenders::Mode(SkBlendMode::kColorDodge) });

        run_test(keyContext, gatherer, reporter, paintOptions, /* expectedNumOptions= */ 1);
    }

    // Specifying the BlendMode PrecompileBlender by SkBlendMode should also only ever
    // yield 1 combination.
    {
        PaintOptions paintOptions;
        paintOptions.setBlendModes({ SkBlendMode::kSrcOver });

        run_test(keyContext, gatherer, reporter, paintOptions, /* expectedNumOptions= */ 1);
    }

    // The Arithmetic PrecompileBlender only ever has 1 combination
    {
        PaintOptions paintOptions;
        paintOptions.setBlenders({ PrecompileBlenders::Arithmetic() });

        run_test(keyContext, gatherer, reporter, paintOptions, /* expectedNumOptions= */ 1);
    }
}

// Exercise all the PrecompileShaders factories
void shader_subtest(const KeyContext& keyContext,
                    PipelineDataGatherer* gatherer,
                    skiatest::Reporter* reporter) {
    {
        PaintOptions paintOptions;
        paintOptions.setShaders({ PrecompileShaders::Empty() });

        run_test(keyContext, gatherer, reporter, paintOptions, /* expectedNumOptions= */ 1);
    }

    // The solid color shader only ever generates one combination. Because it is constant
    // everywhere it can cause other shaders to be elided (e.g., the LocalMatrix shader -
    // see the LocalMatrix test(s) below).
    {
        PaintOptions paintOptions;
        paintOptions.setShaders({ PrecompileShaders::Color() });

        run_test(keyContext, gatherer, reporter, paintOptions,
                 /* expectedNumOptions= */ kExpectedSolidColorCombos);
    }

    // In general, the blend shader generates the product of the options in each of its slots.
    // The rules for how many combinations the SkBlendModes yield are:
    //   all Porter-Duff SkBlendModes collapse to one option (see SkBlendMode::kLastCoeffMode)
    //   all non-Porter-Duff SkBlendModes collapse to a second option
    {
        const SkBlendMode kBlendModes[] = {
                SkBlendMode::kScreen,    // Porter-Duff
                SkBlendMode::kSrcOut,    // Porter-Duff
                SkBlendMode::kDarken,    // non-Porter-Duff
                SkBlendMode::kHardLight, // non-Porter-Duff
        };
        PaintOptions paintOptions;
        paintOptions.setShaders(
                { PrecompileShaders::Blend(SkSpan<const SkBlendMode>(kBlendModes),
                                           { PrecompileShaders::Color() },
                                           { PrecompileShaders::MakeFractalNoise() }) });

        run_test(keyContext, gatherer, reporter, paintOptions,
                 /* expectedNumOptions= */ 2 *  // both Porter-Duff and non-Porter-Duff
                                           kExpectedSolidColorCombos *
                                           kExpectedPerlinNoiseCombos);
    }

    // The ImageShaders have 6 combinations (3 sampling/tiling x 2 alpha/non-alpha)
    // The CoordClamp shader doesn't add any additional combinations to its wrapped shader.
    {
        PaintOptions paintOptions;
        paintOptions.setShaders({ PrecompileShaders::CoordClamp({ PrecompileShaders::Image() }) });

        run_test(keyContext, gatherer, reporter, paintOptions,
                 /* expectedNumOptions= */ kExpectedImageCombos);
    }

    // RawImageShaders only have 3 combinations (since they never incorporate alpha)
    {
        PaintOptions paintOptions;
        paintOptions.setShaders({ PrecompileShaders::RawImage() });

        run_test(keyContext, gatherer, reporter, paintOptions,
                 /* expectedNumOptions= */ kExpectedRawImageCombos);
    }

    // Each Perlin noise shader only has one combination
    {
        PaintOptions paintOptions;
        paintOptions.setShaders({ PrecompileShaders::MakeFractalNoise(),
                                  PrecompileShaders::MakeTurbulence() });

        run_test(keyContext, gatherer, reporter, paintOptions,
                 /* expectedNumOptions= */ kExpectedPerlinNoiseCombos + kExpectedPerlinNoiseCombos);
    }

    // Each gradient shader generates 3 combinations
    {
        PaintOptions paintOptions;
        paintOptions.setShaders({ PrecompileShaders::LinearGradient(),
                                  PrecompileShaders::RadialGradient(),
                                  PrecompileShaders::TwoPointConicalGradient(),
                                  PrecompileShaders::SweepGradient() });

        run_test(keyContext, gatherer, reporter, paintOptions,
                 /* expectedNumOptions= */ kExpectedGradientCombos + kExpectedGradientCombos +
                                           kExpectedGradientCombos + kExpectedGradientCombos);
    }

    // Each picture shader generates 12 combinations:
    //    2 (pictureShader LM) x 6 (imageShader variations)
    {
        PaintOptions paintOptions;
        paintOptions.setShaders({ PrecompileShaders::Picture() });

        run_test(keyContext, gatherer, reporter, paintOptions,
                 /* expectedNumOptions= */ kExpectedPictureCombos);
    }

    // In general, the local matrix shader just generates however many options its wrapped
    // shader generates.
    {
        PaintOptions paintOptions;
        paintOptions.setShaders(
                { PrecompileShaders::LocalMatrix({ PrecompileShaders::LinearGradient() }) });

        run_test(keyContext, gatherer, reporter, paintOptions,
                 /* expectedNumOptions= */ kExpectedGradientCombos);
    }

    // The ColorFilter shader just creates the cross product of its child options
    {
        PaintOptions paintOptions;
        paintOptions.setShaders(
                { PrecompileShaders::ColorFilter({ PrecompileShaders::LinearGradient() },
                                                 { PrecompileColorFilters::Blend() }) });

        run_test(keyContext, gatherer, reporter, paintOptions,
                 /* expectedNumOptions= */ kExpectedGradientCombos * kExpectedBlendCFCombos);
    }

    {
        PaintOptions paintOptions;
        paintOptions.setShaders(
                { PrecompileShaders::WorkingColorSpace({ PrecompileShaders::LinearGradient() },
                                                       { SkColorSpace::MakeSRGBLinear() }) });

        run_test(keyContext, gatherer, reporter, paintOptions,
                 /* expectedNumOptions= */ kExpectedGradientCombos *
                                           1 /* only one colorSpace */);
    }
}

// Exercise all the PrecompileColorFilters factories. The impact of colorfilters on the number
// of combinations is very predictable. Except for the Compose and Lerp color filters, all the
// color filters only ever have one combination. The Compose and Lerp color filters also just
// simply generate the cross product of their children.
void colorfilter_subtest(const KeyContext& keyContext,
                         PipelineDataGatherer* gatherer,
                         skiatest::Reporter* reporter) {


    {
        // The compose colorfilter just generates the cross product of its children.
        static constexpr int kExpectedNumOptions =
                kExpectedTableCFCombos * (kExpectedHighContrastCFCombos + kExpectedLumaCFCombos) +
                kExpectedLightingCFCombos * (kExpectedHighContrastCFCombos + kExpectedLumaCFCombos);

        PaintOptions paintOptions;
        paintOptions.setColorFilters(
            { PrecompileColorFilters::Compose(
                    { PrecompileColorFilters::Table(), PrecompileColorFilters::Lighting() },
                    { PrecompileColorFilters::HighContrast(), PrecompileColorFilters::Luma() }) });

        run_test(keyContext, gatherer, reporter, paintOptions, kExpectedNumOptions);
    }

    {
        PaintOptions paintOptions;
        paintOptions.setColorFilters({ PrecompileColorFilters::Blend() });

        run_test(keyContext, gatherer, reporter, paintOptions, kExpectedBlendCFCombos);
    }

    {
        PaintOptions paintOptions;
        paintOptions.setColorFilters({ PrecompileColorFilters::Matrix(),
                                       PrecompileColorFilters::HSLAMatrix() });

        // HSLAMatrix and Matrix map to the same color filter
        run_test(keyContext, gatherer, reporter, paintOptions,
                 kExpectedMatrixCFCombos + kExpectedMatrixCFCombos);
    }

    {
        PaintOptions paintOptions;
        paintOptions.setColorFilters({ PrecompileColorFilters::LinearToSRGBGamma(),
                                       PrecompileColorFilters::SRGBToLinearGamma() });

        // LinearToSRGB and SRGBToLinear both map to the colorspace colorfilter
        run_test(keyContext, gatherer, reporter, paintOptions,
                 kExpectedColorSpaceCFCombos + kExpectedColorSpaceCFCombos);
    }

    {
        // The lerp colorfilter just generates the cross product of its children.
        static constexpr int kExpectedNumOptions =
                kExpectedMatrixCFCombos * (kExpectedBlendCFCombos + kExpectedOverdrawCFCombos) +
                kExpectedLumaCFCombos * (kExpectedBlendCFCombos + kExpectedOverdrawCFCombos);

        PaintOptions paintOptions;
        paintOptions.setColorFilters(
            { PrecompileColorFilters::Lerp(
                    { PrecompileColorFilters::Matrix(), PrecompileColorFilters::Luma() },
                    { PrecompileColorFilters::Blend(), PrecompileColorFilters::Overdraw() }) });

        run_test(keyContext, gatherer, reporter, paintOptions, kExpectedNumOptions);
    }
}

} // anonymous namespace

DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(CombinationBuilderTest, reporter, context,
                                   CtsEnforcement::kNextRelease) {
    ShaderCodeDictionary* dict = context->priv().shaderCodeDictionary();

    auto rtEffectDict = std::make_unique<RuntimeEffectDictionary>();

    SkColorInfo ci(kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
    KeyContext keyContext(context->priv().caps(),
                          dict,
                          rtEffectDict.get(),
                          ci,
                          /* dstTexture= */ nullptr,
                          /* dstOffset= */ {0, 0});

    PipelineDataGatherer gatherer(Layout::kMetal);

    // The default PaintOptions should create a single combination with a solid color shader and
    // kSrcOver blending
    {
        PaintOptions paintOptions;

        run_test(keyContext, &gatherer, reporter, paintOptions, /* expectedNumOptions= */ 1);
    }

    blend_subtest(keyContext, &gatherer, reporter);
    shader_subtest(keyContext, &gatherer, reporter);
    colorfilter_subtest(keyContext, &gatherer, reporter);

    no_blend_mode_option_test(keyContext, &gatherer, reporter);
    big_test(keyContext, &gatherer, reporter);
    runtime_effect_test(keyContext, &gatherer, reporter);
}

#endif // SK_GRAPHITE
