/*
 * 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/PrecompileRuntimeEffect.h"
#include "include/gpu/graphite/precompile/PrecompileShader.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/KeyContext.h"
#include "src/gpu/graphite/PipelineData.h"
#include "src/gpu/graphite/PrecompileInternal.h"
#include "src/gpu/graphite/RenderPassDesc.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 = 15;
static constexpr int kExpectedColorSpaceCFCombos = 1;
static constexpr int kExpectedHighContrastCFCombos = 1;
static constexpr int kExpectedLumaCFCombos = 1;
static constexpr int kExpectedMatrixCFCombos = 2; // alpha-preserving and not
static constexpr int kExpectedLightingCFCombos = kExpectedMatrixCFCombos; // Maps to ::Matrix
static constexpr int kExpectedOverdrawCFCombos = 1;
static constexpr int kExpectedTableCFCombos = 1;

// shaders
static constexpr int kExpectedGradientCombos = 6;
static constexpr int kExpectedImageCombos = 24;
static constexpr int kExpectedPerlinNoiseCombos = 1;
static constexpr int kExpectedPictureCombos = 48;
static constexpr int kExpectedRawImageCombos = 10;
static constexpr int kExpectedSolidColorCombos = 2;

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

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

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

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

// 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,
              const RenderPassDesc& renderPassDesc,
              skiatest::Reporter* reporter,
              const PaintOptions& paintOptions,
              int expectedNumOptions) {
    REPORTER_ASSERT(reporter, paintOptions.priv().numCombinations() == expectedNumOptions,
                    "expected %d, but was %d",
                    expectedNumOptions, paintOptions.priv().numCombinations());

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

    // Some combinations produced may result in the same UniquePaintParamsID since the combinatorics
    // introduce opaque vs. non-opaque branches. Depending on how that recombines in the final
    // paint key, key-impacting decisions may or may not be made. In most cases, the number of
    // unique paint IDs will be lower than the raw number of combinations. Since we don't de-dupe
    // when adding to `precompileIDs` here, we can assert the total is `expectedNumOptions`.
    SkASSERT(static_cast<int>(precompileIDs.size()) == expectedNumOptions);
}

void big_test(const KeyContext& keyContext,
              const RenderPassDesc& renderPassDesc,
              skiatest::Reporter* reporter) {

    static constexpr int kNumExpected = 6360;
    // paintOptions (6360 = 4*1590)
    //  |- (1590 = 6+1584) sweepGrad_0 (3*2) |
    //  |                blendShader_0 (1584 = 1*8*198)
    //  |                 |- 0: (1)       kSrc (1)
    //  |                 |- 1: (8=6+2)   (dsts) linearGrad_0 (3*2) | solid_0 (2)
    //  |                 |- 2: (198=6+192) (srcs) linearGrad_1 (3*2) |
    //  |                                        blendShader_1 (192=1*8*24)
    //  |                                         |- 0: (1) kDst (1)
    //  |                                         |- 1: (8=6+2) (dsts) radGrad_0 (3*2) | solid_1 (2)
    //  |                                         |- 2: (24) (srcs) imageShader_0 (24)
    //  |
    //  |- (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, expected %d",
                    paintOptions.priv().numCombinations(),
                    kNumExpected);

    std::vector<UniquePaintParamsID> precompileIDs;
    paintOptions.priv().buildCombinations(keyContext,
                                          DrawTypeFlags::kNone,
                                          /* withPrimitiveBlender= */ false,
                                          Coverage::kNone,
                                          renderPassDesc,
                                          [&precompileIDs](UniquePaintParamsID id,
                                                           DrawTypeFlags,
                                                           bool /* withPrimitiveBlender */,
                                                           Coverage,
                                                           const RenderPassDesc&) {
                                                               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* blueCode,
        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 [blueEffect, error3] = effectFactory(SkString(blueCode));
    REPORTER_ASSERT(reporter, blueEffect, "%s", error3.c_str());
    auto [combineEffect, error4] = effectFactory(SkString(combineCode));
    REPORTER_ASSERT(reporter, combineEffect, "%s", error4.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> blue = precompileFactory(blueEffect, {});
    REPORTER_ASSERT(reporter, blue);

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

    return { combine };
}

void runtime_effect_test(const KeyContext& keyContext,
                         const RenderPassDesc& renderPassDesc,
                         skiatest::Reporter* reporter) {
    // paintOptions (64 = 4*4*4)
    //  |- combineShader (4)
    //  |       0: redShader  | greenShader
    //  |       1: blueShader | nullptr
    //  |
    //  |- combineColorFilter (4)
    //  |       0: redColorFilter  | greenColorFilter
    //  |       1: blueColorFilter | nullptr
    //  |
    //  |- combineBlender (4)
    //  |       0: redBlender  | greenBlender
    //  |       1: blueBlender | nullptr

    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* kBlueS = R"(
            half4 main(vec2 fragcoord) { return half4(0, 0, .5, .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,
                                                    PrecompileRuntimeEffects::MakePrecompileShader,
                                                    kRedS,
                                                    kGreenS,
                                                    kBlueS,
                                                    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* kBlueCF = R"(
            half4 main(half4 color) { return half4(0, 0, .5, .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,
                    PrecompileRuntimeEffects::MakePrecompileColorFilter,
                    kRedCF,
                    kGreenCF,
                    kBlueCF,
                    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* kBlueB = R"(
            half4 main(half4 src, half4 dst) { return half4(0, 0, .5, .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,
                    PrecompileRuntimeEffects::MakePrecompileBlender,
                    kRedB,
                    kGreenB,
                    kBlueB,
                    kCombineB);
        paintOptions.setBlenders(combinations);
    }

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

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

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

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

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

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

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

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

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

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

        run_test(keyContext, renderPassDesc, 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, renderPassDesc, 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 GetPorterDuffBlendConstants))
    //   all HSCL SkBlendModes collapse to another option
    //   all other SkBlendModes produce unique options
    {
        const SkBlendMode kBlendModes[] = {
                SkBlendMode::kSrcOut,    // Porter-Duff
                SkBlendMode::kSrcOver,   // Porter-Duff
                SkBlendMode::kHue,       // HSLC
                SkBlendMode::kColor,     // HSLC
                SkBlendMode::kScreen,    // Fixed Screen
                SkBlendMode::kDarken,    // fixed Darken
        };
        PaintOptions paintOptions;
        paintOptions.setShaders({{
                PrecompileShaders::Blend(SkSpan<const SkBlendMode>(kBlendModes),
                                         {{ PrecompileShaders::Color() }},
                                         {{ PrecompileShaders::MakeFractalNoise() }})
        }});

        run_test(keyContext, renderPassDesc, reporter, paintOptions,
                 /* expectedNumOptions= */ 4 *  // Porter-Duff, HSLC, Screen, Darken
                                           kExpectedSolidColorCombos *
                                           kExpectedPerlinNoiseCombos);
    }

    // The ImageShaders have 24 combinations
    // (6 sampling/tiling x 4 color space xform)
    // The CoordClamp shader doesn't add any additional combinations to its wrapped shader.
    {
        PaintOptions paintOptions;
        paintOptions.setShaders({{
            PrecompileShaders::CoordClamp({{ PrecompileShaders::Image() }})
        }});

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

    // RawImageShaders only have 10 combinations since they never do cubic filtering and only have
    // two possible color space xform variants.
    {
        PaintOptions paintOptions;
        paintOptions.setShaders({{ PrecompileShaders::RawImage() }});

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

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

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

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

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

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

        run_test(keyContext, renderPassDesc, 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, renderPassDesc, 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, renderPassDesc, reporter, paintOptions,
                 /* expectedNumOptions= */ kExpectedGradientCombos * kExpectedBlendCFCombos);
    }

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

        run_test(keyContext, renderPassDesc, 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,
                         const RenderPassDesc& renderPassDesc,
                         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, renderPassDesc, reporter, paintOptions, kExpectedNumOptions);
    }

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

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

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

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

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

        // LinearToSRGB and SRGBToLinear both map to the colorspace colorfilter
        run_test(keyContext, renderPassDesc, 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, renderPassDesc, reporter, paintOptions, kExpectedNumOptions);
    }
}

} // anonymous namespace

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

    sk_sp<RuntimeEffectDictionary> rtEffectDict = sk_make_sp<RuntimeEffectDictionary>();

    SkColorInfo ci(kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
    FloatStorageManager floatStorageManager;
    PaintParamsKeyBuilder builder(dict);
    PipelineDataGatherer gatherer(Layout::kMetal);
    KeyContext keyContext(context->priv().caps(), &floatStorageManager, &builder, &gatherer, dict,
                          rtEffectDict, ci);

    RenderPassDesc unusedRenderPassDesc;

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

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

    blend_subtest(keyContext, unusedRenderPassDesc, reporter);
    shader_subtest(keyContext, unusedRenderPassDesc, reporter);
    colorfilter_subtest(keyContext, unusedRenderPassDesc, reporter);

    no_blend_mode_option_test(keyContext, unusedRenderPassDesc, reporter);
    big_test(keyContext, unusedRenderPassDesc, reporter);
    runtime_effect_test(keyContext, unusedRenderPassDesc, reporter);
}

#endif // SK_GRAPHITE
