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

#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkTypes.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/GrTypes.h"
#include "include/private/base/SkTDArray.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/base/SkRandom.h"
#include "src/gpu/AtlasTypes.h"
#include "src/gpu/SkBackingFit.h"
#include "src/gpu/Swizzle.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrOpFlushState.h"
#include "src/gpu/ganesh/GrProxyProvider.h"
#include "src/gpu/ganesh/GrRenderTargetProxy.h"
#include "src/gpu/ganesh/GrSurfaceProxy.h"
#include "src/gpu/ganesh/GrSurfaceProxyView.h"
#include "src/gpu/ganesh/GrTextureProxy.h"
#include "src/gpu/ganesh/GrTextureResolveManager.h"
#include "src/gpu/ganesh/ops/GrOp.h"
#include "src/gpu/ganesh/ops/OpsTask.h"
#include "tests/CtsEnforcement.h"
#include "tests/Test.h"

#include <algorithm>
#include <array>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <utility>
#include <vector>

class GrAppliedClip;
class GrDrawingManager;
class GrDstProxyView;
class GrRecordingContext;
class SkArenaAlloc;
enum class GrXferBarrierFlags;
struct GrContextOptions;

// We create Ops that write a value into a range of a buffer. We create ranges from
// kNumOpPositions starting positions x kRanges canonical ranges. We repeat each range kNumRepeats
// times (with a different value written by each of the repeats).
namespace {
struct Range {
    unsigned fOffset;
    unsigned fLength;
};

static constexpr int kNumOpPositions = 4;
static constexpr Range kRanges[] = {{0, 4,}, {1, 2}};
static constexpr int kNumRanges = (int)std::size(kRanges);
static constexpr int kNumRepeats = 2;
static constexpr int kNumOps = kNumRepeats * kNumOpPositions * kNumRanges;

static constexpr uint64_t fact(int n) {
    assert(n > 0);
    return n > 1 ? n * fact(n - 1) : 1;
}

// How wide should our result buffer be to hold values written by the ranges of the ops.
static constexpr unsigned result_width() {
    unsigned maxLength = 0;
    for (size_t i = 0; i < kNumRanges; ++i) {
        maxLength = maxLength > kRanges[i].fLength ? maxLength : kRanges[i].fLength;
    }
    return kNumOpPositions + maxLength - 1;
}

// Number of possible allowable binary chainings among the kNumOps ops.
static constexpr int kNumCombinableValues = fact(kNumOps) / fact(kNumOps - 2);
using Combinable = std::array<GrOp::CombineResult, kNumCombinableValues>;

/**
 * The index in Combinable for the result for combining op 'b' into op 'a', i.e. the result of
 * op[a]->combineIfPossible(op[b]).
 */
int64_t combinable_index(int a, int b) {
    SkASSERT(b != a);
    // Each index gets kNumOps - 1 contiguous bools
    int64_t aOffset = a * (kNumOps - 1);
    // Within a's range we have one value each other op, but not one for a itself.
    int64_t bIdxInA = b < a ? b : b - 1;
    return aOffset + bIdxInA;
}

/**
 * Creates a legal set of combinability results for the ops. The likelihood that any two ops
 * in a group can merge is randomly chosen.
 */
static void init_combinable(int numGroups, Combinable* combinable, SkRandom* random) {
    SkScalar mergeProbability = random->nextUScalar1();
    std::fill_n(combinable->begin(), kNumCombinableValues, GrOp::CombineResult::kCannotCombine);
    SkTDArray<int> groups[kNumOps];
    for (int i = 0; i < kNumOps; ++i) {
        auto& group = groups[random->nextULessThan(numGroups)];
        for (int g = 0; g < group.size(); ++g) {
            int j = group[g];
            if (random->nextUScalar1() < mergeProbability) {
                (*combinable)[combinable_index(i, j)] = GrOp::CombineResult::kMerged;
            } else {
                (*combinable)[combinable_index(i, j)] = GrOp::CombineResult::kMayChain;
            }
            if (random->nextUScalar1() < mergeProbability) {
                (*combinable)[combinable_index(j, i)] = GrOp::CombineResult::kMerged;
            } else {
                (*combinable)[combinable_index(j, i)] = GrOp::CombineResult::kMayChain;
            }
        }
        group.push_back(i);
    }
}

/**
 * A simple test op. It has an integer position, p. When it executes it writes p into an array
 * of ints at index p and p+1. It takes a bitfield that indicates allowed pair-wise chainings.
 */
class TestOp : public GrOp {
public:
    DEFINE_OP_CLASS_ID

    static GrOp::Owner Make(GrRecordingContext* context, int value, const Range& range,
                            int result[], const Combinable* combinable) {
        return GrOp::Make<TestOp>(context, value, range, result, combinable);
    }

    const char* name() const override { return "TestOp"; }

    void writeResult(int result[]) const {
        for (const auto& op : ChainRange<TestOp>(this)) {
            for (const auto& vr : op.fValueRanges) {
                for (unsigned i = 0; i < vr.fRange.fLength; ++i) {
                    result[vr.fRange.fOffset + i] = vr.fValue;
                }
            }
        }
    }

private:
    friend class ::GrOp;  // for ctor

    TestOp(int value, const Range& range, int result[], const Combinable* combinable)
            : INHERITED(ClassID()), fResult(result), fCombinable(combinable) {
        fValueRanges.push_back({value, range});
        this->setBounds(SkRect::MakeXYWH(range.fOffset, 0, range.fOffset + range.fLength, 1),
                        HasAABloat::kNo, IsHairline::kNo);
    }

    void onPrePrepare(GrRecordingContext*,
                      const GrSurfaceProxyView& writeView,
                      GrAppliedClip*,
                      const GrDstProxyView&,
                      GrXferBarrierFlags renderPassXferBarriers,
                      GrLoadOp colorLoadOp) override {}

    void onPrepare(GrOpFlushState*) override {}

    void onExecute(GrOpFlushState*, const SkRect& chainBounds) override {
        for (auto& op : ChainRange<TestOp>(this)) {
            op.writeResult(fResult);
        }
    }

    CombineResult onCombineIfPossible(GrOp* t, SkArenaAlloc* arenas, const GrCaps&) override {
        // This op doesn't use the arenas, but make sure the OpsTask is sending it
        SkASSERT(arenas);
        (void) arenas;
        auto that = t->cast<TestOp>();
        int v0 = fValueRanges[0].fValue;
        int v1 = that->fValueRanges[0].fValue;
        auto result = (*fCombinable)[combinable_index(v0, v1)];
        if (result == GrOp::CombineResult::kMerged) {
            std::move(that->fValueRanges.begin(), that->fValueRanges.end(),
                      std::back_inserter(fValueRanges));
        }
        return result;
    }

    struct ValueRange {
        int fValue;
        Range fRange;
    };
    std::vector<ValueRange> fValueRanges;
    int* fResult;
    const Combinable* fCombinable;

    using INHERITED = GrOp;
};
}  // namespace

/**
 * Tests adding kNumOps to an op list with all possible allowed chaining configurations. Tests
 * adding the ops in all possible orders and verifies that the chained executions don't violate
 * painter's order.
 */
DEF_GANESH_TEST(OpChainTest, reporter, /*ctxInfo*/, CtsEnforcement::kApiLevel_T) {
    sk_sp<GrDirectContext> dContext = GrDirectContext::MakeMock(nullptr);
    SkASSERT(dContext);
    const GrCaps* caps = dContext->priv().caps();
    static constexpr SkISize kDims = {kNumOps + 1, 1};

    const GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kRGBA_8888,
                                                                 GrRenderable::kYes);

    static const GrSurfaceOrigin kOrigin = kTopLeft_GrSurfaceOrigin;
    auto proxy = dContext->priv().proxyProvider()->createProxy(format,
                                                               kDims,
                                                               GrRenderable::kYes,
                                                               1,
                                                               GrMipmapped::kNo,
                                                               SkBackingFit::kExact,
                                                               skgpu::Budgeted::kNo,
                                                               GrProtected::kNo,
                                                               /*label=*/"OpChainTest",
                                                               GrInternalSurfaceFlags::kNone);
    SkASSERT(proxy);
    proxy->instantiate(dContext->priv().resourceProvider());

    skgpu::Swizzle writeSwizzle = caps->getWriteSwizzle(format, GrColorType::kRGBA_8888);

    int result[result_width()];
    int validResult[result_width()];

    int permutation[kNumOps];
    for (int i = 0; i < kNumOps; ++i) {
        permutation[i] = i;
    }
    // Op order permutations.
    static constexpr int kNumPermutations = 100;
    // For a given number of chainability groups, this is the number of random combinability reuslts
    // we will test.
    static constexpr int kNumCombinabilitiesPerGrouping = 20;
    SkRandom random;
    bool repeat = false;
    Combinable combinable;
    GrDrawingManager* drawingMgr = dContext->priv().drawingManager();
    sk_sp<GrArenas> arenas = sk_make_sp<GrArenas>();
    for (int p = 0; p < kNumPermutations; ++p) {
        for (int i = 0; i < kNumOps - 2 && !repeat; ++i) {
            // The current implementation of nextULessThan() is biased. :(
            unsigned j = i + random.nextULessThan(kNumOps - i);
            std::swap(permutation[i], permutation[j]);
        }
        // g is the number of chainable groups that we partition the ops into.
        for (int g = 1; g < kNumOps; ++g) {
            for (int c = 0; c < kNumCombinabilitiesPerGrouping; ++c) {
                init_combinable(g, &combinable, &random);
                skgpu::TokenTracker tracker;
                GrOpFlushState flushState(dContext->priv().getGpu(),
                                          dContext->priv().resourceProvider(),
                                          &tracker);
                skgpu::v1::OpsTask opsTask(drawingMgr,
                                           GrSurfaceProxyView(proxy, kOrigin, writeSwizzle),
                                           dContext->priv().auditTrail(),
                                           arenas);
                // This assumes the particular values of kRanges.
                std::fill_n(result, result_width(), -1);
                std::fill_n(validResult, result_width(), -1);
                for (int i = 0; i < kNumOps; ++i) {
                    int value = permutation[i];
                    // factor out the repeats and then use the canonical starting position and range
                    // to determine an actual range.
                    int j = value % (kNumRanges * kNumOpPositions);
                    int pos = j % kNumOpPositions;
                    Range range = kRanges[j / kNumOpPositions];
                    range.fOffset += pos;
                    auto op = TestOp::Make(dContext.get(), value, range, result, &combinable);
                    TestOp* testOp = (TestOp*)op.get();
                    testOp->writeResult(validResult);
                    opsTask.addOp(drawingMgr, std::move(op),
                                  GrTextureResolveManager(dContext->priv().drawingManager()),
                                  *caps);
                }
                opsTask.makeClosed(dContext.get());
                opsTask.prepare(&flushState);
                opsTask.execute(&flushState);
                opsTask.endFlush(drawingMgr);
                opsTask.disown(drawingMgr);
#if 0  // Useful to repeat a random configuration that fails the test while debugger attached.
                if (!std::equal(result, result + result_width(), validResult)) {
                    repeat = true;
                }
#endif
                (void)repeat;
                REPORTER_ASSERT(reporter, std::equal(result, result + result_width(), validResult));
            }
        }
    }
}
