/*
 * Copyright 2021 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "fuzz/Fuzz.h"
#include "fuzz/FuzzCommon.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkDeferredDisplayList.h"
#include "include/core/SkDeferredDisplayListRecorder.h"
#include "include/core/SkExecutor.h"
#include "include/core/SkPromiseImageTexture.h"
#include "include/core/SkSize.h"
#include "include/core/SkSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "include/private/base/SkDeque.h"
#include "include/private/base/SkMutex.h"
#include "include/private/base/SkNoncopyable.h"
#include "include/private/base/SkTemplates.h"
#include "include/private/base/SkThreadID.h"
#include "src/core/SkTaskGroup.h"
#include "src/image/SkImage_Gpu.h"
#include "tools/gpu/GrContextFactory.h"

#include <atomic>
#include <memory>
#include <queue>

using namespace skia_private;
using ContextType = sk_gpu_test::GrContextFactory::ContextType;

// be careful: `foo(make_fuzz_t<T>(f), make_fuzz_t<U>(f))` is undefined.
// In fact, all make_fuzz_foo() functions have this potential problem.
// Use sequence points!
template <typename T>
inline T make_fuzz_t(Fuzz* fuzz) {
    T t;
    fuzz->next(&t);
    return t;
}

class DDLFuzzer;

// This class stores the state of a given promise image owned by the fuzzer. It acts as the
// context for the callback procs of the promise image.
class PromiseImageInfo : public SkNVRefCnt<PromiseImageInfo>, SkNoncopyable {
public:
    enum class State : int {
        kInitial,
        kTriedToFulfill,
        kDone
    };
    ~PromiseImageInfo() {
        // If we hit this, then the image or the texture will outlive this object which is bad.
        SkASSERT_RELEASE(!fImage || fImage->unique());
        SkASSERT_RELEASE(!fTexture || fTexture->unique());
        fImage.reset();
        fTexture.reset();
        State s = fState;
        SkASSERT_RELEASE(s == State::kDone);
    }
    DDLFuzzer* fFuzzer = nullptr;
    sk_sp<SkImage> fImage;
    // At the moment, the atomicity of this isn't used because all our promise image callbacks
    // happen on the same thread. See the TODO below about them unreffing them off the GPU thread.
    std::atomic<State> fState{State::kInitial};
    sk_sp<SkPromiseImageTexture> fTexture;
};

static constexpr int kPromiseImageCount = 8;
static constexpr SkISize kPromiseImageSize{16, 16};
static constexpr int kPromiseImagesPerDDL = 4;
static constexpr int kRecordingThreadCount = 4;
static constexpr int kIterationCount = 10000;

// A one-shot runner object for fuzzing our DDL threading. It creates an array of promise images,
// and concurrently records DDLs that reference them, playing each DDL back on the GPU thread.
// The backing textures for promise images may be recycled into a pool, or not, for each case
// as determined by the fuzzing data.
class DDLFuzzer : SkNoncopyable {
public:
    DDLFuzzer(Fuzz*, ContextType);
    void run();

    sk_sp<SkPromiseImageTexture> fulfillPromiseImage(PromiseImageInfo&);
    void releasePromiseImage(PromiseImageInfo&);
private:
    void initPromiseImage(int index);
    void recordAndPlayDDL();
    bool isOnGPUThread() const { return SkGetThreadID() == fGpuThread; }
    bool isOnMainThread() const { return SkGetThreadID() == fMainThread; }

    Fuzz* fFuzz = nullptr;
    GrDirectContext* fContext = nullptr;
    AutoTArray<PromiseImageInfo> fPromiseImages{kPromiseImageCount};
    sk_sp<SkSurface> fSurface;
    SkSurfaceCharacterization fSurfaceCharacterization;
    std::unique_ptr<SkExecutor> fGpuExecutor = SkExecutor::MakeFIFOThreadPool(1, false);
    std::unique_ptr<SkExecutor> fRecordingExecutor =
        SkExecutor::MakeFIFOThreadPool(kRecordingThreadCount, false);
    SkTaskGroup fGpuTaskGroup{*fGpuExecutor};
    SkTaskGroup fRecordingTaskGroup{*fRecordingExecutor};
    SkThreadID fGpuThread = kIllegalThreadID;
    SkThreadID fMainThread = SkGetThreadID();
    std::queue<sk_sp<SkPromiseImageTexture>> fReusableTextures;
    sk_gpu_test::GrContextFactory fContextFactory;
};

DDLFuzzer::DDLFuzzer(Fuzz* fuzz, ContextType contextType) : fFuzz(fuzz) {
    sk_gpu_test::ContextInfo ctxInfo = fContextFactory.getContextInfo(contextType);
    sk_gpu_test::TestContext* testCtx = ctxInfo.testContext();
    fContext = ctxInfo.directContext();
    if (!fContext) {
        return;
    }
    SkISize canvasSize = kPromiseImageSize;
    canvasSize.fWidth *= kPromiseImagesPerDDL;
    SkImageInfo ii = SkImageInfo::Make(canvasSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
    fSurface = SkSurface::MakeRenderTarget(fContext, skgpu::Budgeted::kNo, ii);
    if (!fSurface || !fSurface->characterize(&fSurfaceCharacterization)) {
        return;
    }

    testCtx->makeNotCurrent();
    fGpuTaskGroup.add([&]{
        testCtx->makeCurrent();
        fGpuThread = SkGetThreadID();
    });
    fGpuTaskGroup.wait();
    for (int i = 0; i < kPromiseImageCount; ++i) {
        this->initPromiseImage(i);
    }
}

sk_sp<SkPromiseImageTexture> DDLFuzzer::fulfillPromiseImage(PromiseImageInfo& promiseImage) {
    using State = PromiseImageInfo::State;
    if (!this->isOnGPUThread()) {
        fFuzz->signalBug();
    }
    bool success = make_fuzz_t<bool>(fFuzz);
    State prior = promiseImage.fState.exchange(State::kTriedToFulfill, std::memory_order_relaxed);
    if (prior != State::kInitial || promiseImage.fTexture != nullptr) {
        fFuzz->signalBug();
    }
    if (!success) {
        return nullptr;
    }

    // Try reusing an existing texture if we can and if the fuzzer wills it.
    if (!fReusableTextures.empty() && make_fuzz_t<bool>(fFuzz)) {
        promiseImage.fTexture = std::move(fReusableTextures.front());
        fReusableTextures.pop();
        return promiseImage.fTexture;
    }

    bool finishedBECreate = false;
    auto markFinished = [](void* context) {
        *(bool*)context = true;
    };

    GrBackendTexture backendTex =
            fContext->createBackendTexture(kPromiseImageSize.width(),
                                           kPromiseImageSize.height(),
                                           kRGBA_8888_SkColorType,
                                           SkColors::kRed,
                                           GrMipmapped::kNo,
                                           GrRenderable::kYes,
                                           GrProtected::kNo,
                                           markFinished,
                                           &finishedBECreate,
                                           /*label=*/"DDLFuzzer_FulFillPromiseImage");
    SkASSERT_RELEASE(backendTex.isValid());
    while (!finishedBECreate) {
        fContext->checkAsyncWorkCompletion();
    }

    promiseImage.fTexture = SkPromiseImageTexture::Make(backendTex);

    return promiseImage.fTexture;
}

void DDLFuzzer::releasePromiseImage(PromiseImageInfo& promiseImage) {
    using State = PromiseImageInfo::State;
    // TODO: This requirement will go away when we unref promise images off the GPU thread.
    if (!this->isOnGPUThread()) {
        fFuzz->signalBug();
    }
    State old = promiseImage.fState.exchange(State::kInitial, std::memory_order_relaxed);
    if (old != State::kTriedToFulfill) {
        fFuzz->signalBug();
    }

    // If we failed to fulfill, then nothing to be done.
    if (!promiseImage.fTexture) {
        return;
    }

    bool reuse = make_fuzz_t<bool>(fFuzz);
    if (reuse) {
        fReusableTextures.push(std::move(promiseImage.fTexture));
    } else {
        fContext->deleteBackendTexture(promiseImage.fTexture->backendTexture());
    }
    promiseImage.fTexture = nullptr;
}

static sk_sp<SkPromiseImageTexture> fuzz_promise_image_fulfill(void* ctxIn) {
    PromiseImageInfo& fuzzPromiseImage = *(PromiseImageInfo*)ctxIn;
    return fuzzPromiseImage.fFuzzer->fulfillPromiseImage(fuzzPromiseImage);
}

static void fuzz_promise_image_release(void* ctxIn) {
    PromiseImageInfo& fuzzPromiseImage = *(PromiseImageInfo*)ctxIn;
    fuzzPromiseImage.fFuzzer->releasePromiseImage(fuzzPromiseImage);
}

void DDLFuzzer::initPromiseImage(int index) {
    PromiseImageInfo& promiseImage = fPromiseImages[index];
    promiseImage.fFuzzer = this;
    GrBackendFormat backendFmt = fContext->defaultBackendFormat(kRGBA_8888_SkColorType,
                                                                GrRenderable::kYes);
    promiseImage.fImage = SkImage::MakePromiseTexture(fContext->threadSafeProxy(),
                                                      backendFmt,
                                                      kPromiseImageSize,
                                                      GrMipmapped::kNo,
                                                      kTopLeft_GrSurfaceOrigin,
                                                      kRGBA_8888_SkColorType,
                                                      kUnpremul_SkAlphaType,
                                                      SkColorSpace::MakeSRGB(),
                                                      &fuzz_promise_image_fulfill,
                                                      &fuzz_promise_image_release,
                                                      &promiseImage);
}

void DDLFuzzer::recordAndPlayDDL() {
    SkASSERT(!this->isOnGPUThread() && !this->isOnMainThread());
    SkDeferredDisplayListRecorder recorder(fSurfaceCharacterization);
    SkCanvas* canvas = recorder.getCanvas();
    // Draw promise images in a strip
    for (int i = 0; i < kPromiseImagesPerDDL; i++) {
        int xOffset = i * kPromiseImageSize.width();
        int j;
        // Pick random promise images to draw.
        fFuzz->nextRange(&j, 0, kPromiseImageCount - 1);
        canvas->drawImage(fPromiseImages[j].fImage, xOffset, 0);
    }
    sk_sp<SkDeferredDisplayList> ddl = recorder.detach();
    fGpuTaskGroup.add([=, ddl{std::move(ddl)}]{
        bool success = fSurface->draw(std::move(ddl));
        if (!success) {
            fFuzz->signalBug();
        }
    });
}

void DDLFuzzer::run() {
    if (!fSurface) {
        return;
    }
    fRecordingTaskGroup.batch(kIterationCount, [=](int i) {
        this->recordAndPlayDDL();
    });
    fRecordingTaskGroup.wait();
    fGpuTaskGroup.add([=] {
        while (!fReusableTextures.empty()) {
            sk_sp<SkPromiseImageTexture> gpuTexture = std::move(fReusableTextures.front());
            fContext->deleteBackendTexture(gpuTexture->backendTexture());
            fReusableTextures.pop();
        }
        fContextFactory.destroyContexts();
        // TODO: Release promise images not on the GPU thread.
        fPromiseImages.reset(0);
    });
    fGpuTaskGroup.wait();
}

DEF_FUZZ(DDLThreadingGL, fuzz) {
    DDLFuzzer(fuzz, ContextType::kGL_ContextType).run();
}
