/*
 * Copyright 2024 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/gpu/graphite/BackendTexture.h"
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/Image.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/Surface.h"
#include "src/core/SkAutoPixmapStorage.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "tools/gpu/ManagedBackendTexture.h"
#include "tools/graphite/GraphiteTestContext.h"

using namespace skgpu;
using namespace skgpu::graphite;

DEF_CONDITIONAL_GRAPHITE_TEST_FOR_ALL_CONTEXTS(ImageWrapTextureMipmapsTest,
                                               reporter,
                                               context,
                                               testContext,
                                               true,
                                               CtsEnforcement::kApiLevel_V) {
    auto recorder = context->makeRecorder();
    if (!recorder) {
        ERRORF(reporter, "Could not make recorder");
        return;
    }

    skgpu::Protected isProtected = skgpu::Protected(context->priv().caps()->protectedSupport());

    auto info = SkImageInfo::Make({2, 1}, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
    SkAutoPixmapStorage basePM, topPM;
    basePM.alloc(info);
    basePM.erase(SK_ColorGREEN);
    topPM.alloc(info.makeDimensions({1, 1}));
    topPM.erase(SK_ColorBLUE);

    SkPixmap levelPMs[]{basePM, topPM};
    auto mbet = sk_gpu_test::ManagedGraphiteTexture::MakeMipmappedFromPixmaps(recorder.get(),
                                                                              levelPMs,
                                                                              Renderable::kNo,
                                                                              isProtected);

    if (!mbet) {
        ERRORF(reporter, "Could not make backend texture");
        return;
    }

    std::unique_ptr<Recording> recording = recorder->snap();

    auto recordingFinishProc = [](void* context, CallbackResult) {
        std::unique_ptr<Recording>(static_cast<Recording*>(context));
    };

    skgpu::graphite::InsertRecordingInfo recordingInfo;
    recordingInfo.fFinishedProc = recordingFinishProc;
    recordingInfo.fRecording = recording.get();
    recordingInfo.fFinishedContext = recording.release();
    if (!context->insertRecording(recordingInfo)) {
        ERRORF(reporter, "Could not insert recording");
        return;
    }

    static constexpr struct TestCase {
        SkImages::GenerateMipmapsFromBase genMipmaps;
        SkColor expectedColor;
    } kTestCases[]{{SkImages::GenerateMipmapsFromBase::kNo , 0xFFFF0000},
                   {SkImages::GenerateMipmapsFromBase::kYes, 0XFF00FF00}};

    for (const auto& testCase : kTestCases) {
        recorder = context->makeRecorder();
        if (!recorder) {
            ERRORF(reporter, "Could not make recorder");
            return;
        }

        auto image = SkImages::WrapTexture(recorder.get(),
                                           mbet->texture(),
                                           info.colorType(),
                                           info.alphaType(),
                                           info.refColorSpace(),
                                           Origin::kTopLeft,
                                           testCase.genMipmaps,
                                           sk_gpu_test::ManagedGraphiteTexture::ImageReleaseProc,
                                           mbet->releaseContext());
        if (!recorder) {
            ERRORF(reporter, "Could not make image");
            return;
        }

        // We determe the contents of the image's top level by doing a downsampling draw to a
        // surface and then reading the surface's contents.
        auto surface = SkSurfaces::RenderTarget(recorder.get(), info.makeDimensions({1, 1}));
        if (!recorder) {
            ERRORF(reporter, "Could not make surface");
            return;
        }

        auto shader = image->makeShader(
                SkTileMode::kRepeat,
                SkTileMode::kRepeat,
                SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNearest));

        surface->getCanvas()->scale(0.05f, 0.05f);
        SkPaint paint;
        paint.setShader(std::move(shader));
        surface->getCanvas()->drawPaint(paint);

        recording = recorder->snap();
        recordingInfo.fRecording = recording.get();
        recordingInfo.fFinishedContext = recording.release();
        if (!context->insertRecording(recordingInfo)) {
            ERRORF(reporter, "Could not insert recording");
            return;
        }

        struct ReadContext {
            bool called = false;
            bool success = false;
            uint32_t color;
        };
        auto readPixelsCallback = [](SkImage::ReadPixelsContext context,
                                     std::unique_ptr<const SkImage::AsyncReadResult> result) {
            auto& readContext = *static_cast<ReadContext*>(context);
            readContext.called = true;
            if (result) {
                readContext.success = true;
                readContext.color = *static_cast<const uint32_t*>(result->data(0));
            }
        };
        ReadContext readContext;
        context->asyncRescaleAndReadPixels(surface.get(),
                                           surface->imageInfo(),
                                           SkIRect::MakeSize(surface->imageInfo().dimensions()),
                                           SkImage::RescaleGamma::kSrc,
                                           SkImage::RescaleMode::kNearest,
                                           readPixelsCallback,
                                           &readContext);
        context->submit();
        while (!readContext.called) {
            testContext->tick();
            context->checkAsyncWorkCompletion();
        }

        if (!readContext.success) {
            ERRORF(reporter, "Read pixels failed");
            return;
        }

        REPORTER_ASSERT(reporter, readContext.color == testCase.expectedColor);
    }
}
