/*
 * 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"

#include "include/core/SkBlendMode.h"
#include "include/gpu/graphite/Recorder.h"
#include "src/gpu/SkBackingFit.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/ContextUtils.h"
#include "src/gpu/graphite/Device.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/Renderer.h"
#include "src/gpu/graphite/TextureInfoPriv.h"
#include "src/gpu/graphite/TextureProxyView.h"

using namespace skgpu;
using namespace skgpu::graphite;

// These are unit tests that ensure the secondary "inner fill" draw is recorded when possible.
DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(InnerFillTest, reporter, context,
                                   CtsEnforcement::kNextRelease) {

    std::unique_ptr<Recorder> recorder = context->makeRecorder();
    sk_sp<Device> device = Device::Make(recorder.get(),
                                        SkImageInfo::Make(512, 512,
                                                          kRGBA_8888_SkColorType,
                                                          kPremul_SkAlphaType),
                                        Budgeted::kYes,
                                        Mipmapped::kNo,
                                        SkBackingFit::kExact,
                                        /*surfaceProps=*/{},
                                        LoadOp::kClear,
                                        "inner-fill");

    // Default rrect size is sufficient to avoid the small-size exclusion criteria
    auto testRRect = [&](const SkPaint& paint, bool innerFillExpected, float rrectSize = 128.f) {
        SkRRect rrect = SkRRect::MakeRectXY(SkRect::MakeXYWH(0.f, 0.f, rrectSize, rrectSize),
                                            0.1f * rrectSize, 0.1f * rrectSize);
        int initialRenderSteps = device->testingOnly_pendingRenderSteps();
        int initialTasks = recorder->priv().numRootTasks();
        device->drawRRect(rrect, paint);

        int actualRenderSteps = device->testingOnly_pendingRenderSteps();
        if (recorder->priv().numRootTasks() != initialTasks) {
            // Flushed for a dst read copy before appending the new draw and possibly inner fill.
            initialRenderSteps = 0;
        }

        // TODO(michaelludwig): After migrating to the layer draw tracking system, having a way to
        // traverse the recorded draws and inspect them could let these checks be more robust, e.g.
        // one of the steps is actually the CoverBoundsRenderStep AND it's in the front.
        int expectedRenderSteps = initialRenderSteps + (innerFillExpected ? 2 : 1);
        REPORTER_ASSERT(reporter, actualRenderSteps == expectedRenderSteps,
                        "Expected (%d) vs Actual (%d)", expectedRenderSteps, actualRenderSteps);
    };

    // ** Test cases that should not produce an inner fill:
    // 1. A transparent paint, so the draw is not eligible for an inner fill
    {
        skiatest::ReporterContext label{reporter, "transparent paint"};
        SkPaint transparentPaint;
        transparentPaint.setAlphaf(0.5f);
        testRRect(transparentPaint, /*innerFillExpected=*/false);
    }
    // 2. A very small rounded rectangle that would otherwise have an inner fill
    {
        skiatest::ReporterContext label{reporter, "small rrect"};
        testRRect(SkPaint(), /*innerFillExpected=*/false, /*rrectSize=*/8.f);
    }
    // 3. An opaque paint that has a blend mode that still mixes with the dst
    {
        skiatest::ReporterContext label{reporter, "fancy blend"};
        SkPaint opaqueBlendedPaint;
        opaqueBlendedPaint.setBlendMode(SkBlendMode::kSrcIn);
        testRRect(opaqueBlendedPaint, /*innerFillExpected=*/false);
    }

    // ** Test cases that shouldn't produce an inner fill due to analytic clipping
    device->pushClipStack();
    device->clipShader(SkShaders::Color({0.1f, 0.2f, 0.3f, 0.5f}, nullptr),
                        SkClipOp::kIntersect);
    // 4. An opaque paint but with an analytic clip
    {
        skiatest::ReporterContext label{reporter, "opaque src-over analytic clip"};
        testRRect(SkPaint(), /*innerFillExpected=*/false);
    }
    // 5. A kSrc paint but there is analytic clip
    {
        skiatest::ReporterContext label{reporter, "src w/ analytic clip"};
        SkPaint srcPaint;
        srcPaint.setBlendMode(SkBlendMode::kSrc);
        testRRect(srcPaint, /*innerFillExpected=*/false);
    }
    device->popClipStack();

    // ** Test cases that should produce an inner fill:
    // 1. A kSrcOver paint with opaque color (or shader)
    {
        skiatest::ReporterContext label{reporter, "opaque src-over"};
        testRRect(SkPaint(), /*innerFillExpected=*/true);
    }
    // 2. A kSrc paint when the device supports HW blending regardless of coverage
    {
        skiatest::ReporterContext label{reporter, "src"};
        SkPaint srcPaint;
        srcPaint.setBlendMode(SkBlendMode::kSrc);
        srcPaint.setAlphaf(0.5f); // emphasize it's src color is not opaque
        testRRect(srcPaint, /*innerFillExpected=*/true);
    }

    // We don't actually care about rendering, so just throw everything away
}
