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

#include "include/core/SkColorSpace.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 "src/gpu/graphite/Surface_Graphite.h"
#include "tests/TestUtils.h"
#include "tools/ToolUtils.h"
#include "tools/graphite/GraphiteTestContext.h"

using namespace skgpu;
using namespace skgpu::graphite;

namespace {
const SkISize kSize = { 32, 32 };
constexpr int kNumMipLevels = 6;

constexpr SkColor4f kColors[6] = {
    { 1.0f, 0.0f, 0.0f, 1.0f }, // R
    { 0.0f, 1.0f, 0.0f, 0.9f }, // G
    { 0.0f, 0.0f, 1.0f, 0.7f }, // B
    { 0.0f, 1.0f, 1.0f, 0.5f }, // C
    { 1.0f, 0.0f, 1.0f, 0.3f }, // M
    { 1.0f, 1.0f, 0.0f, 0.2f }, // Y
};

constexpr SkColor4f kColorsNew[6] = {
    { 1.0f, 1.0f, 0.0f, 0.2f },  // Y
    { 1.0f, 0.0f, 0.0f, 1.0f },  // R
    { 0.0f, 1.0f, 0.0f, 0.9f },  // G
    { 0.0f, 0.0f, 1.0f, 0.7f },  // B
    { 0.0f, 1.0f, 1.0f, 0.5f },  // C
    { 1.0f, 0.0f, 1.0f, 0.3f },  // M
};

void check_solid_pixmap(skiatest::Reporter* reporter,
                        const SkColor4f& expected,
                        const SkPixmap& actual,
                        SkColorType ct,
                        const char* label) {
    const float kTols[4] = { 0.01f, 0.01f, 0.01f, 0.01f };

    auto error = std::function<ComparePixmapsErrorReporter>(
        [reporter, ct, label, expected](int x, int y, const float diffs[4]) {
            SkASSERT(x >= 0 && y >= 0);
            ERRORF(reporter, "%s %s - mismatch at %d, %d "
                             "expected: (%.2f, %.2f, %.2f, %.2f) "
                             "- diffs: (%.2f, %.2f, %.2f, %.2f)",
                   ToolUtils::colortype_name(ct), label, x, y,
                   expected.fR, expected.fG, expected.fB, expected.fA,
                   diffs[0], diffs[1], diffs[2], diffs[3]);
        });

    CheckSolidPixels(expected, actual, kTols, error);
}

void update_backend_texture(Recorder* recorder,
                            const BackendTexture& backendTex,
                            SkColorType ct,
                            bool withMips,
                            const SkColor4f colors[6],
                            GpuFinishedProc finishedProc = nullptr,
                            GpuFinishedContext finishedCtx = nullptr) {
    SkPixmap pixmaps[6];
    std::unique_ptr<char[]> memForPixmaps;

    int numMipLevels = ToolUtils::make_pixmaps(ct, kPremul_SkAlphaType, withMips, colors, pixmaps,
                                               &memForPixmaps);
    SkASSERT(numMipLevels == 1 || numMipLevels == kNumMipLevels);
    SkASSERT(kSize == pixmaps[0].dimensions());

    recorder->updateBackendTexture(backendTex, pixmaps, numMipLevels, finishedProc, finishedCtx);

}

BackendTexture create_backend_texture(skiatest::Reporter* reporter,
                                      const Caps* caps,
                                      Recorder* recorder,
                                      SkColorType ct,
                                      bool withMips,
                                      Renderable renderable,
                                      skgpu::Protected isProtected,
                                      const SkColor4f colors[6],
                                      GpuFinishedProc finishedProc = nullptr,
                                      GpuFinishedContext finishedCtx = nullptr) {
    Mipmapped mipmapped = withMips ? Mipmapped::kYes : Mipmapped::kNo;
    TextureInfo info = caps->getDefaultSampledTextureInfo(ct,
                                                          mipmapped,
                                                          isProtected,
                                                          renderable);

    BackendTexture backendTex = recorder->createBackendTexture(kSize, info);
    REPORTER_ASSERT(reporter, backendTex.isValid());

    update_backend_texture(recorder, backendTex, ct, withMips, colors, finishedProc, finishedCtx);

    return backendTex;
}

sk_sp<SkImage> wrap_backend_texture(skiatest::Reporter* reporter,
                                    Recorder* recorder,
                                    const skgpu::graphite::BackendTexture& backendTex,
                                    SkColorType ct,
                                    bool withMips) {
    sk_sp<SkImage> image = SkImages::WrapTexture(recorder,
                                                 backendTex,
                                                 ct,
                                                 kPremul_SkAlphaType,
                                                 /* colorSpace= */ nullptr);
    REPORTER_ASSERT(reporter, image);
    REPORTER_ASSERT(reporter, image->hasMipmaps() == withMips);

    return image;
}

void check_levels(skiatest::Reporter* reporter,
                  Context* context,
                  Recorder* recorder,
                  SkImage* image,
                  bool withMips,
                  const SkColor4f colors[6]) {
    int numLevels = withMips ? kNumMipLevels : 1;

    SkSamplingOptions sampling = withMips
                                 ? SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNearest)
                                 : SkSamplingOptions(SkFilterMode::kNearest);

    SkImageInfo surfaceII = SkImageInfo::Make(kSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
    sk_sp<SkSurface> surf = SkSurfaces::RenderTarget(recorder, surfaceII, Mipmapped::kNo);
    SkCanvas* canvas = surf->getCanvas();

    for (int i = 0, drawSize = kSize.width(); i < numLevels; ++i, drawSize /= 2) {
        if (i == 5) {
            // TODO: Metal currently never draws the top-most mip-level (skbug.com/13792)
            continue;
        }

        SkImageInfo readbackII = SkImageInfo::Make({drawSize, drawSize}, kRGBA_8888_SkColorType,
                                                   kUnpremul_SkAlphaType);
        SkAutoPixmapStorage actual;
        SkAssertResult(actual.tryAlloc(readbackII));
        actual.erase(SkColors::kTransparent);

        SkPaint paint;
        paint.setBlendMode(SkBlendMode::kSrc);

        canvas->clear(SkColors::kTransparent);

#if 0
        // This option gives greater control over the tilemodes and texture scaling
        SkMatrix lm;
        lm.setScale(1.0f / (1 << i), 1.0f / (1 << i));

        paint.setShader(image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, sampling, lm));
        canvas->drawRect(SkRect::MakeWH(drawSize, drawSize), paint);
#else
        canvas->drawImageRect(image, SkRect::MakeWH(drawSize, drawSize), sampling, &paint);
#endif

        if (!surf->readPixels(actual, 0, 0)) {
            ERRORF(reporter, "readPixels failed");
            return;
        }

        SkString str;
        str.appendf("mip-level %d", i);

        check_solid_pixmap(reporter, colors[i], actual, image->colorType(), str.c_str());
    }
}

} // anonymous namespace

DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(UpdateImageBackendTextureTest, reporter, context,
                                         CtsEnforcement::kApiLevel_V) {
    const Caps* caps = context->priv().caps();
    std::unique_ptr<Recorder> recorder = context->makeRecorder();

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

    // TODO: test more than just RGBA8
    for (SkColorType ct : { kRGBA_8888_SkColorType }) {
        for (bool withMips : { true, false }) {
            for (Renderable renderable : { Renderable::kYes, Renderable::kNo }) {

                BackendTexture backendTex = create_backend_texture(reporter, caps, recorder.get(),
                                                                   ct, withMips, renderable,
                                                                   isProtected, kColors);

                sk_sp<SkImage> image = wrap_backend_texture(reporter, recorder.get(), backendTex,
                                                            ct, withMips);
                if (!image) {
                    continue;
                }

                if (isProtected == skgpu::Protected::kNo) {
                    check_levels(reporter, context, recorder.get(), image.get(), withMips, kColors);
                }

                image.reset();

                update_backend_texture(recorder.get(), backendTex, ct, withMips, kColorsNew);

                image = wrap_backend_texture(reporter, recorder.get(), backendTex, ct, withMips);
                if (!image) {
                    continue;
                }

                if (isProtected == skgpu::Protected::kNo) {
                    check_levels(reporter, context, recorder.get(), image.get(), withMips,
                                 kColorsNew);
                }

                image.reset();

                recorder->deleteBackendTexture(backendTex);
            }
        }
    }
}

DEF_CONDITIONAL_GRAPHITE_TEST_FOR_ALL_CONTEXTS(UpdateBackendTextureFinishedProcTest,
                                               reporter,
                                               context,
                                               testContext,
                                               true,
                                               CtsEnforcement::kNextRelease) {
    const Caps* caps = context->priv().caps();
    std::unique_ptr<Recorder> recorder = context->makeRecorder();

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

    struct FinishContext {
        bool fFinishedUpdate = false;
        skiatest::Reporter* fReporter = nullptr;
    };
    FinishContext finishCtx;
    finishCtx.fReporter = reporter;

    auto finishedProc = [](void* ctx, CallbackResult) {
        FinishContext* finishedCtx = (FinishContext*) ctx;
        REPORTER_ASSERT(finishedCtx->fReporter, !(finishedCtx->fFinishedUpdate));
        finishedCtx->fFinishedUpdate = true;
    };

    BackendTexture backendTex = create_backend_texture(reporter,
                                                       caps,
                                                       recorder.get(),
                                                       kRGBA_8888_SkColorType,
                                                       /*withMips=*/false,
                                                       Renderable::kNo,
                                                       isProtected,
                                                       kColors,
                                                       finishedProc,
                                                       &finishCtx);

    REPORTER_ASSERT(reporter, !finishCtx.fFinishedUpdate);

    std::unique_ptr<Recording> recording = recorder->snap();
    if (!recording) {
        ERRORF(reporter, "Failed to make recording");
        return;
    }
    InsertRecordingInfo insertInfo;
    insertInfo.fRecording = recording.get();
    context->insertRecording(insertInfo);

    REPORTER_ASSERT(reporter, !finishCtx.fFinishedUpdate);

    testContext->syncedSubmit(context);
    REPORTER_ASSERT(reporter, finishCtx.fFinishedUpdate);

    recorder->deleteBackendTexture(backendTex);
}
