/*
 * 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/SkImage.h"
#include "include/gpu/GpuTypes.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/Recording.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 "src/gpu/graphite/Texture.h"
#include "src/gpu/graphite/TextureProxy.h"
#include "tests/TestUtils.h"
#include "tools/ToolUtils.h"

using namespace skgpu::graphite;
using Mipmapped = skgpu::Mipmapped;

namespace {

// We draw the larger image into the smaller surface to force mipmapping
const SkISize kImageSize = { 32, 32 };
SkDEBUGCODE(constexpr int kNumMipLevels = 6;)
const SkISize kSurfaceSize = { 16, 16 };

constexpr int kNumMutations = 2;
constexpr SkColor4f kInitialColor = SkColors::kRed;
constexpr SkColor4f kMutationColors[kNumMutations] = {
    SkColors::kGreen,
    SkColors::kBlue
};

/*
 * We have 3 use cases. In each case there is a mutating task which changes the contents of an
 * image (somehow) and a shared redraw task which just creates a single Recording which draws the
 * image that is being mutated. The mutator's image must start off being 'kInitialColor' and
 * then cycle through 'kMutationColors'. The mutation tasks are:

 *  1) (AHBs) The client has wrapped a backend texture in an image and is changing the backend
 *     texture's contents.
 *  2) (Volatile Promise Images) The client has a pool of backend textures and updates both the
 *     contents of the backend textures and which one backs the image every frame
 *  3) (Surface/Image pair) The client has a surface and has snapped an image w/o a copy but
 *     keeps drawing to the surface
 *
 * There are also two scenarios for the mutation and redrawing tasks:
 *  a) Both use the same recorder
 *  b) They use separate recorders
 * The latter, obviously, requires more synchronization.
 */

// Base class for the 3 mutation methods.
//    init   - should create the SkImage that is going to be changing
//    mutate - should change the contents of the SkImage
class Mutator {
public:
    Mutator(skiatest::Reporter* reporter, Recorder* recorder, bool withMips)
            : fReporter(reporter)
            , fRecorder(recorder)
            , fWithMips(withMips) {
    }
    virtual ~Mutator() = default;

    virtual std::unique_ptr<Recording> init(const Caps*) = 0;
    virtual std::unique_ptr<Recording> mutate(int mutationIndex) = 0;
    virtual int getCase() const = 0;

    SkImage* getMutatingImage() {
        return fMutatingImg.get();
    }

protected:
    skiatest::Reporter* fReporter;
    Recorder* fRecorder;
    bool fWithMips;

    sk_sp<SkImage> fMutatingImg; // needs to be created in the 'init' method
};

// This class puts the 3 mutation use cases through their paces.
//    init - creates the single Recording that draws the mutator's image
//    checkResult - verifies that replaying the Recording results in the expected/mutated color
class Redrawer {
public:
    Redrawer(skiatest::Reporter* reporter, Recorder* recorder)
            : fReporter(reporter)
            , fRecorder(recorder) {
        SkImageInfo ii = SkImageInfo::Make(kSurfaceSize,
                                           kRGBA_8888_SkColorType,
                                           kPremul_SkAlphaType);
        fReadbackPM.alloc(ii);
    }

    void init(SkImage* imageToDraw) {
        SkImageInfo ii = SkImageInfo::Make(kSurfaceSize,
                                           kRGBA_8888_SkColorType,
                                           kPremul_SkAlphaType);
        fImgDrawSurface = SkSurfaces::RenderTarget(fRecorder, ii, Mipmapped::kNo);
        REPORTER_ASSERT(fReporter, fImgDrawSurface);

        fImgDrawRecording = MakeRedrawRecording(fRecorder, fImgDrawSurface.get(), imageToDraw);
    }

    Recording* imgDrawRecording() {
        return fImgDrawRecording.get();
    }

    // This is here bc it uses a lot from the Redrawer (i.e., its recorder, its surface, etc.).
    void checkResult(Context* context,
                     int testcaseID,
                     bool useTwoRecorders,
                     bool withMips,
                     const SkColor4f& expectedColor) {

        fReadbackPM.erase(SkColors::kTransparent);

        if (!fImgDrawSurface->readPixels(fReadbackPM, 0, 0)) {
            ERRORF(fReporter, "readPixels failed");
        }

        auto error = std::function<ComparePixmapsErrorReporter>(
                [&](int x, int y, const float diffs[4]) {
                    ERRORF(fReporter,
                           "case %d%c - %s: "
                           "expected (%.1f %.1f %.1f %.1f) "
                           "- diffs (%.1f, %.1f, %.1f, %.1f)",
                           testcaseID, useTwoRecorders ? 'b' : 'a',
                           withMips ? "mipmapped" : "not-mipmapped",
                           expectedColor.fR, expectedColor.fG, expectedColor.fB, expectedColor.fA,
                           diffs[0], diffs[1], diffs[2], diffs[3]);
                });

        static constexpr float kTol[] = {0, 0, 0, 0};
        CheckSolidPixels(expectedColor, fReadbackPM, kTol, error);
    }

private:
    static std::unique_ptr<Recording> MakeRedrawRecording(Recorder* recorder,
                                                          SkSurface* surfaceToDrawTo,
                                                          SkImage* imageToDraw) {
        SkSamplingOptions sampling = SkSamplingOptions(SkFilterMode::kLinear,
                                                       SkMipmapMode::kNearest);

        SkCanvas* canvas = surfaceToDrawTo->getCanvas();

        canvas->clear(SkColors::kTransparent);
        canvas->drawImageRect(imageToDraw,
                              SkRect::MakeWH(kSurfaceSize.width(), kSurfaceSize.height()),
                              sampling);

        return recorder->snap();
    }

    skiatest::Reporter* fReporter;
    Recorder* fRecorder;

    sk_sp<SkSurface> fImgDrawSurface;
    std::unique_ptr<Recording> fImgDrawRecording;

    SkAutoPixmapStorage fReadbackPM;
};

void update_backend_texture(skiatest::Reporter* reporter,
                            Recorder* recorder,
                            const BackendTexture& backendTex,
                            SkColorType ct,
                            bool withMips,
                            SkColor4f color) {
    SkPixmap pixmaps[6];
    std::unique_ptr<char[]> memForPixmaps;

    const SkColor4f colors[6] = { color, color, color, color, color, color };

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

    REPORTER_ASSERT(reporter, recorder->updateBackendTexture(backendTex, pixmaps, numMipLevels));
}

// case 1 (AHBs)
// To simulate the AHB use case this Mutator creates a BackendTexture and an SkImage that wraps
// it. To mutate the SkImage it simply updates the BackendTexture.
class UpdateBackendTextureMutator : public Mutator {
public:
    static std::unique_ptr<Mutator> Make(skiatest::Reporter* reporter,
                                         Recorder* recorder,
                                         bool withMips) {
        return std::make_unique<UpdateBackendTextureMutator>(reporter, recorder, withMips);
    }

    UpdateBackendTextureMutator(skiatest::Reporter* reporter, Recorder* recorder, bool withMips)
            : Mutator(reporter, recorder, withMips) {
    }
    ~UpdateBackendTextureMutator() override {
        fRecorder->deleteBackendTexture(fBETexture);
    }

    std::unique_ptr<Recording> init(const Caps* caps) override {
        // Note: not renderable
        TextureInfo info = caps->getDefaultSampledTextureInfo(kRGBA_8888_SkColorType,
                                                              fWithMips ? Mipmapped::kYes
                                                                        : Mipmapped::kNo,
                                                              skgpu::Protected::kNo,
                                                              skgpu::Renderable::kNo);
        REPORTER_ASSERT(fReporter, info.isValid());

        fBETexture = fRecorder->createBackendTexture(kImageSize, info);
        REPORTER_ASSERT(fReporter, fBETexture.isValid());

        update_backend_texture(fReporter, fRecorder, fBETexture, kRGBA_8888_SkColorType,
                               fWithMips, kInitialColor);

        fMutatingImg = SkImages::AdoptTextureFrom(fRecorder,
                                                  fBETexture,
                                                  kRGBA_8888_SkColorType,
                                                  kPremul_SkAlphaType,
                                                  /* colorSpace= */ nullptr);
        REPORTER_ASSERT(fReporter, fMutatingImg);

        return fRecorder->snap();
    }

    std::unique_ptr<Recording> mutate(int mutationIndex) override {
        update_backend_texture(fReporter, fRecorder, fBETexture, kRGBA_8888_SkColorType,
                               fWithMips, kMutationColors[mutationIndex]);
        return fRecorder->snap();
    }

    int getCase() const override { return 1; }

private:
    BackendTexture fBETexture;
};

// case 2 (Volatile Promise Images)
// To simulate the hardware video decoder use case this Mutator creates a set of BackendTextures
// and fills them w/ different colors. A single volatile Promise Image is created and is
// fulfilled by the different BackendTextures.
class VolatilePromiseImageMutator : public Mutator {
public:
    static std::unique_ptr<Mutator> Make(skiatest::Reporter* reporter,
                                         Recorder* recorder,
                                         bool withMips) {
        return std::make_unique<VolatilePromiseImageMutator>(reporter, recorder, withMips);
    }

    VolatilePromiseImageMutator(skiatest::Reporter* reporter, Recorder* recorder, bool withMips)
            : Mutator(reporter, recorder, withMips) {
    }

    ~VolatilePromiseImageMutator() override {
        // We need to delete the mutating image first since it holds onto the backend texture
        // that was last used to fulfill the volatile promise image.
        fMutatingImg.reset();

        fCallbackTracker.finishedTest();

        for (int i = 0; i < kNumMutations+1; ++i) {
            fRecorder->deleteBackendTexture(fBETextures[i]);
        }
    }

    static std::tuple<BackendTexture, void*> fulfill(void* ctx) {
        VolatilePromiseImageMutator* mutator = reinterpret_cast<VolatilePromiseImageMutator*>(ctx);

        int index = mutator->fCallbackTracker.onFulfillCB();

        return { mutator->fBETextures[index], &mutator->fCallbackTracker };
    }

    static void imageRelease(void* ctx) {
        VolatilePromiseImageMutator* mutator = reinterpret_cast<VolatilePromiseImageMutator*>(ctx);

        mutator->fCallbackTracker.onImageReleaseCB();
    }

    static void textureRelease(void* ctx) {
        CallbackTracker* callbackTracker = reinterpret_cast<CallbackTracker*>(ctx);

        callbackTracker->onTextureReleaseCB();
    }

    std::unique_ptr<Recording> init(const Caps* caps) override {
        // Note: not renderable
        TextureInfo info = caps->getDefaultSampledTextureInfo(kRGBA_8888_SkColorType,
                                                              fWithMips ? Mipmapped::kYes
                                                                        : Mipmapped::kNo,
                                                              skgpu::Protected::kNo,
                                                              skgpu::Renderable::kNo);
        REPORTER_ASSERT(fReporter, info.isValid());

        fBETextures[0] = fRecorder->createBackendTexture(kImageSize, info);
        REPORTER_ASSERT(fReporter, fBETextures[0].isValid());

        update_backend_texture(fReporter, fRecorder, fBETextures[0], kRGBA_8888_SkColorType,
                               fWithMips, kInitialColor);

        for (int i = 0; i < kNumMutations; ++i) {
            fBETextures[i+1] = fRecorder->createBackendTexture(kImageSize, info);
            REPORTER_ASSERT(fReporter, fBETextures[i+1].isValid());

            update_backend_texture(fReporter, fRecorder, fBETextures[i+1], kRGBA_8888_SkColorType,
                                   fWithMips, kMutationColors[i]);
        }

        fMutatingImg = SkImages::PromiseTextureFrom(fRecorder,
                                                    kImageSize,
                                                    info,
                                                    SkColorInfo(kRGBA_8888_SkColorType,
                                                                kPremul_SkAlphaType,
                                                                /* colorSpace= */ nullptr),
                                                    Volatile::kYes,
                                                    fulfill,
                                                    imageRelease,
                                                    textureRelease,
                                                    this);
        REPORTER_ASSERT(fReporter, fMutatingImg);

        return fRecorder->snap();
    }

    std::unique_ptr<Recording> mutate(int mutationIndex) override {
        fCallbackTracker.onMutation();
        return nullptr;
    }

    int getCase() const override { return 2; }

private:
    class CallbackTracker {
    public:
        CallbackTracker() {
            for (int i = 0; i < kNumMutations+1; ++i) {
                fFulfilled[i] = false;
                fReleased[i] = false;
            }
        }

        void onMutation() {
            // In this use case, the active mutation occurs in the volatile promise image callbacks.
            ++fMutationCount;
        }

        int onFulfillCB() {
            SkASSERT(fMutationCount < kNumMutations+1);
            SkASSERT(fFulfilledCount == fMutationCount);
            // For this unit test we should only be fulfilling with each backend texture only once
            SkASSERT(!fFulfilled[fFulfilledCount]);
            SkASSERT(!fReleased[fFulfilledCount]);

            fFulfilled[fFulfilledCount] = true;
            return fFulfilledCount++;
        }

        void onImageReleaseCB() {
            SkASSERT(!fImageReleased);
            fImageReleased = true;
        }

        void onTextureReleaseCB() {
            SkASSERT(fReleasedCount >= 0 && fReleasedCount < kNumMutations+1);

            SkASSERT(fFulfilled[fReleasedCount]);
            SkASSERT(!fReleased[fReleasedCount]);
            fReleased[fReleasedCount] = true;
            fReleasedCount++;
        }

        void finishedTest() const {
            SkASSERT(fMutationCount == kNumMutations);
            SkASSERT(fImageReleased);

            for (int i = 0; i < kNumMutations+1; ++i) {
                SkASSERT(fFulfilled[i]);
                SkASSERT(fReleased[i]);
            }
        }

    private:
        int fMutationCount = 0;
        int fFulfilledCount = 0;
        bool fImageReleased = false;
        int fReleasedCount = 0;
        bool fFulfilled[kNumMutations+1];
        bool fReleased[kNumMutations+1];
    };

    CallbackTracker fCallbackTracker;

    BackendTexture fBETextures[kNumMutations+1];
};

// case 3 (Surface/Image pair)
// This mutator creates an SkSurface/SkImage pair that share the same backend object.
// Mutation is accomplished by simply drawing to the SkSurface.
class SurfaceMutator : public Mutator {
public:
    static std::unique_ptr<Mutator> Make(skiatest::Reporter* reporter,
                                         Recorder* recorder,
                                         bool withMips) {
        return std::make_unique<SurfaceMutator>(reporter, recorder, withMips);
    }

    SurfaceMutator(skiatest::Reporter* reporter, Recorder* recorder, bool withMips)
            : Mutator(reporter, recorder, withMips) {
    }

    std::unique_ptr<Recording> init(const Caps* /* caps */) override {
        SkImageInfo ii = SkImageInfo::Make(kImageSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);

        fMutatingSurface = SkSurfaces::RenderTarget(
                fRecorder, ii, fWithMips ? Mipmapped::kYes : Mipmapped::kNo);
        REPORTER_ASSERT(fReporter, fMutatingSurface);

        fMutatingSurface->getCanvas()->clear(kInitialColor);

        fMutatingImg = fMutatingSurface->asImage();
        REPORTER_ASSERT(fReporter, fMutatingImg);

        return fRecorder->snap();
    }

    std::unique_ptr<Recording> mutate(int mutationIndex) override {
        fMutatingSurface->getCanvas()->clear(kMutationColors[mutationIndex]);
        return fRecorder->snap();
    }

    int getCase() const override { return 3; }

private:
    sk_sp<SkSurface> fMutatingSurface;
};

using MutatorFactoryT = std::unique_ptr<Mutator> (*)(skiatest::Reporter*, Recorder*, bool withMips);

void run_test(skiatest::Reporter* reporter,
              Context* context,
              bool useTwoRecorders,
              bool withMips,
              MutatorFactoryT createMutator) {
    const Caps* caps = context->priv().caps();

    std::unique_ptr<Recorder> recorders[2];
    recorders[0] = context->makeRecorder();

    Recorder* mutatorRecorder = recorders[0].get();
    Recorder* redrawerRecorder = recorders[0].get();

    if (useTwoRecorders) {
        recorders[1] = context->makeRecorder();
        redrawerRecorder = recorders[1].get();
    }

    std::unique_ptr<Mutator> mutator = createMutator(reporter, mutatorRecorder, withMips);

    {
        std::unique_ptr<Recording> imgCreationRecording = mutator->init(caps);
        REPORTER_ASSERT(reporter, context->insertRecording({ imgCreationRecording.get() }));
    }

    {
        Redrawer redrawer(reporter, redrawerRecorder);

        redrawer.init(mutator->getMutatingImage());

        REPORTER_ASSERT(reporter, context->insertRecording({ redrawer.imgDrawRecording() }));
        redrawer.checkResult(context, mutator->getCase(),
                             useTwoRecorders, withMips, kInitialColor);

        for (int i = 0; i < kNumMutations; ++i) {
            {
                std::unique_ptr<Recording> imgMutationRecording = mutator->mutate(i);
                if (imgMutationRecording) {
                    REPORTER_ASSERT(reporter,
                                    context->insertRecording({imgMutationRecording.get()}));
                }
            }

            REPORTER_ASSERT(reporter, context->insertRecording({ redrawer.imgDrawRecording() }));
            redrawer.checkResult(context, mutator->getCase(),
                                 useTwoRecorders, withMips, kMutationColors[i]);
        }
    }
}

} // anonymous namespace

DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(MutableImagesTest, reporter, context) {

    for (bool useTwoRecorders : { false, true }) {
        for (bool withMips : { false, true }) {
            // case 1 (AHBs)
            run_test(reporter, context, useTwoRecorders, withMips,
                     UpdateBackendTextureMutator::Make);

            // case 2 (Volatile Promise Images)
            run_test(reporter, context, useTwoRecorders, withMips,
                     VolatilePromiseImageMutator::Make);

            // case 3 (Surface/Image pair)
            if (!withMips) {
                // TODO: allow the mipmapped version when we can automatically regenerate mipmaps
                run_test(reporter, context, useTwoRecorders, withMips,
                         SurfaceMutator::Make);
            }
        }
    }
}
