/*
 * Copyright 2025 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/SkCanvas.h"
#include "include/core/SkPaint.h"
#include "include/core/SkString.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTraceMemoryDump.h"
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/Recording.h"
#include "include/gpu/graphite/Surface.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/ContextUtils.h"
#include "src/gpu/graphite/Renderer.h"
#include "src/gpu/graphite/Surface_Graphite.h"
#include "src/gpu/graphite/TextureFormat.h"
#include "src/gpu/graphite/TextureInfoPriv.h"

namespace skgpu::graphite {

/**
 * Implementation of SkTraceMemoryDump which tracks the number of resources whose type values
 * contain a provided string within a ResourceCache. Could easily be elevated to be shared if other
 * tests could benefit from this utility, but for now is only used within this test.
 */
class ResourceTypeQuantifier : public SkTraceMemoryDump {
public:
    ResourceTypeQuantifier() = delete;
    ~ResourceTypeQuantifier() override {}
    ResourceTypeQuantifier(SkString resourceTypeSubstr) : fResourceTypeSubstr(resourceTypeSubstr) {}

    // Override relevant methods
    void dumpStringValue(const char* dumpName, const char* valueName, const char* value) override {
        if (SkString("type").equals(valueName)) {
            if (SkString(value).contains(fResourceTypeSubstr.c_str())) {
                fNumResourcesWithTypeSubstr++;
            }
        }
    }

    LevelOfDetail getRequestedDetails() const override {
        return SkTraceMemoryDump::kObjectsBreakdowns_LevelOfDetail;
    }

    bool shouldDumpSizelessObjects() const override { return true; }

    // Define methods unique to this implementation
    uint8_t numResourcesWithTypeSubstr() const { return fNumResourcesWithTypeSubstr; }
    void resetCount() { fNumResourcesWithTypeSubstr = 0; }

    // Override unneeded methods to be no-ops
    void setMemoryBacking(const char* dumpName, const char* backingType,
                          const char* backingObjectId) override {}
    void setDiscardableMemoryBacking(
            const char* dumpName, const SkDiscardableMemory& discardableMemoryObject) override {}
    void dumpNumericValue(const char* dumpName, const char* valueName, const char* units,
                          uint64_t value) override {}

private:
    SkString fResourceTypeSubstr;
    int fNumResourcesWithTypeSubstr = 0;
};

/**
 * Unit test to ensure that the Vulkan backend shares renderpasses between draws that do and
 * do not read from the dst texture as intended for optimization purposes. Could be expanded to test
 * every blend mode that reads from the dst against all that do not, but testing just one should be
 * sufficient to prove out that renderpasses can be shared between the different blend/draw types.
 */
DEF_GRAPHITE_TEST_FOR_VULKAN_CONTEXT(VulkanDstReadsShareRenderpass, reporter, context,
                                     CtsEnforcement::kApiLevel_202504) {
    // Set up a render target surface which we should be able to read from as an input attachment.
    // Our Vulkan backend makes render targets usable as input attachments by default.
    const Caps* caps = context->priv().caps();
    std::unique_ptr<Recorder> recorder = context->makeRecorder();
    SkImageInfo ii = SkImageInfo::Make(SkISize::Make(10, 10),
                                       SkColorType::kRGBA_8888_SkColorType,
                                       SkAlphaType::kPremul_SkAlphaType);
    sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(recorder.get(), ii);
    SkCanvas* canvas = surface->getCanvas();
    SharedContext* sharedContext = context->priv().sharedContext();

    TextureFormat targetFormat = TextureInfoPriv::ViewFormat(
            static_cast<const Surface*>(surface.get())->target().proxy()->textureInfo());

    // Select which blend modes to use for testing: one that we do expect to require a dst read on
    // most hardware and one we do not. Assert that the dst read requirements of the modes align to
    // expectations. For the sake of this test, assume Coverage::kNone.
    static const SkBlendMode simpleBlendMode = SkBlendMode::kSrcATop;
    static const SkBlendMode dstReadBlendMode = SkBlendMode::kLighten;

    REPORTER_ASSERT(reporter,
                    CanUseHardwareBlending(caps, targetFormat, simpleBlendMode, Coverage::kNone));
    // VK_EXT_blend_operation_advanced is supported on Nvidia hardware which does enable hardware
    // blending for every Skia blend mode, so the following assertion is not universal.
    // REPORTER_ASSERT(reporter, !CanUseHardwareBlending(caps, dstReadBlendMode, Coverage::kNone));

    // Perform draw operations which do not read from the dst. Clear the canvas to initialize it to
    // any color, drawing a color over it afterwards using the simple blend mode.
    canvas->clear(SK_ColorMAGENTA);
    canvas->drawColor(SK_ColorCYAN, simpleBlendMode);
    std::unique_ptr<Recording> simpleBlendRecording = recorder->snap();

    // Determine the number of renderpasses used for later comparison, asserting we have at least 1.
    ResourceTypeQuantifier renderpassQuantifier { SkString("RenderPass") };
    sharedContext->dumpMemoryStatistics(&renderpassQuantifier);
    const int numRenderPassesNoDstRead = renderpassQuantifier.numResourcesWithTypeSubstr();
    REPORTER_ASSERT(reporter, numRenderPassesNoDstRead > 0);

    // Perform a draw using a blend mode which does require reading from the dst texture. Determine
    // how many renderpasses are in the cache after this operation.
    canvas->drawColor(SK_ColorYELLOW, dstReadBlendMode);
    std::unique_ptr<Recording> dstReadRecording = recorder->snap();
    renderpassQuantifier.resetCount();
    sharedContext->dumpMemoryStatistics(&renderpassQuantifier);
    const int numRenderPassesAfterDstRead = renderpassQuantifier.numResourcesWithTypeSubstr();

    // Assert that no new renderpasses have been added to the cache, meaning that one was reused
    // from the draw that did not require a dst read.
    REPORTER_ASSERT(reporter,
                    numRenderPassesNoDstRead == numRenderPassesAfterDstRead,
                    "# renderpasses with no dst read: %d ; after dst read: %d",
                    numRenderPassesNoDstRead,
                    numRenderPassesAfterDstRead);
}

}  // namespace skgpu::graphite
