/*
 * Copyright 2026 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/SkCanvas.h"
#include "include/core/SkExecutor.h"
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/ContextOptions.h"
#include "include/gpu/graphite/GraphiteTypes.h"
#include "include/gpu/graphite/PrecompileContext.h"
#include "include/gpu/graphite/Surface.h"
#include "include/gpu/graphite/precompile/PaintOptions.h"
#include "include/gpu/graphite/precompile/Precompile.h"
#include "src/core/SkExecutors.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "tools/graphite/GraphiteTestContext.h"
#include "tools/graphite/TestOptions.h"

using namespace::skgpu::graphite;
using namespace skiatest::graphite;

const RenderPassProperties kRGBA_1_D {
        DepthStencilFlags::kDepth,
        kRGBA_8888_SkColorType,
        /* fDstCS= */ nullptr,
        /* fRequiresMSAA= */ false
};

namespace {

void precompile_an_arc_draw(skiatest::Reporter* reporter,
                            PrecompileContext* precompileContext) {
    PaintOptions paintOptions;
    paintOptions.addBlendMode(SkBlendMode::kSrcOver);

    Precompile(precompileContext,
               paintOptions,
               DrawTypeFlags::kCircularArc,
               { kRGBA_1_D });
}

void draw_an_arc(skiatest::Reporter* reporter, Context* context) {
    std::unique_ptr<Recorder> recorder = context->makeRecorder();

    SkImageInfo ii = SkImageInfo::Make(16, 16,
                                       kRGBA_8888_SkColorType,
                                       kPremul_SkAlphaType);


    sk_sp<SkSurface> surf = SkSurfaces::RenderTarget(recorder.get(), ii, skgpu::Mipmapped::kNo);
    SkCanvas* canvas = surf->getCanvas();

    SkArc arc = SkArc::Make(SkRect::MakeWH(16, 16), 0, 270, SkArc::Type::kWedge);
    SkPaint paint;
    paint.setBlendMode(SkBlendMode::kSrcOver);

    canvas->drawArc(arc, paint);

    std::unique_ptr<Recording> recording = recorder->snap();
    if (!recording) {
        ERRORF(reporter, "Failed to make recording");
        return;
    }

    context->insertRecording({ recording.get() });
}

void run_test(skiatest::Reporter* reporter, GraphiteTestContext* testContext,
              const TestOptions& origOptions, bool allowThreads, bool precompileFirst) {
    std::unique_ptr<SkExecutor> executor;
    if (allowThreads) {
        // Ensure the threaded PipelineManager will be used
        executor = SkExecutors::MakeMultiListFIFOThreadPool(/* numWorkLists= */ 2,
                                                            /* threads= */ 1,
                                                            /* allowBorrowing= */ false);
    }

    TestOptions newOptions(origOptions);
    newOptions.fContextOptions.fExecutor = executor.get();

    {
        std::unique_ptr<Context> context = testContext->makeContext(newOptions);
        std::unique_ptr<PrecompileContext> precompileContext = context->makePrecompileContext();

        if (precompileFirst) {
            precompile_an_arc_draw(reporter, precompileContext.get());
        }

        draw_an_arc(reporter, context.get());

        if (!precompileFirst) {
            precompile_an_arc_draw(reporter, precompileContext.get());
        }

        testContext->syncedSubmit(context.get());

        const GlobalCache::PipelineStats stats = context->priv().globalCache()->getStats();
        const PipelineManager::Stats& mgrStats =
                context->priv().sharedContext()->pipelineManager()->getStats();

        REPORTER_ASSERT(reporter, stats.fGraphicsCacheAdditions == 1);
        REPORTER_ASSERT(reporter, mgrStats.fNumTasksCreated == 1);
    }
}

} // anonymous namespace

// The goal here is to test out the PipelineManager's de-duplication of Pipeline
// creation tasks for both threaded and non-threaded PipelineManagers.
// The tests will request the same Pipeline via both Precompilation and drawing -
// altering which one comes first.


// These two tests forcibly create a threaded PipelineManager and then request the
// same Pipeline.
// If precompilation is first the draw should use the precompiled Pipeline.
// If the draw is first the precompilation should just find it.
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_CONTEXTS(PipelineManagerThreadedTest_1,
                                           skgpu::IsRenderingContext,
                                           reporter,
                                           context,
                                           origTestContext,
                                           origOptions,
                                           /* optionsProc= */ nullptr,
                                           /* condition= */ true,
                                           CtsEnforcement::kNever) {
    run_test(reporter,  origTestContext, origOptions,
             /* allowThreads= */ true, /* precompileFirst=*/ true);
}

DEF_CONDITIONAL_GRAPHITE_TEST_FOR_CONTEXTS(PipelineManagerThreadedTest_2,
                                           skgpu::IsRenderingContext,
                                           reporter,
                                           context,
                                           origTestContext,
                                           origOptions,
                                           /* optionsProc= */ nullptr,
                                           /* condition= */ true,
                                           CtsEnforcement::kNever) {
    run_test(reporter, origTestContext, origOptions,
             /* allowThreads= */ true, /* precompileFirst=*/ false);
}

// The next two tests are the same as above but deliberately create a non-threaded
// PipelineManager.
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_CONTEXTS(PipelineManagerThreadedTest_3,
                                           skgpu::IsRenderingContext,
                                           reporter,
                                           context,
                                           origTestContext,
                                           origOptions,
                                           /* optionsProc= */ nullptr,
                                           /* condition= */ true,
                                           CtsEnforcement::kNever) {
    run_test(reporter, origTestContext, origOptions,
             /* allowThreads= */ false, /* precompileFirst=*/ true);
}

DEF_CONDITIONAL_GRAPHITE_TEST_FOR_CONTEXTS(PipelineManagerThreadedTest_4,
                                           skgpu::IsRenderingContext,
                                           reporter,
                                           context,
                                           origTestContext,
                                           origOptions,
                                           /* optionsProc= */ nullptr,
                                           /* condition= */ true,
                                           CtsEnforcement::kNever) {
    run_test(reporter, origTestContext, origOptions,
             /* allowThreads= */ false, /* precompileFirst=*/ false);
}
#endif // SK_GRAPHITE
