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

#include "src/gpu/GrProcessorUnitTest.h"

#include <memory>

#include "include/gpu/GrRecordingContext.h"
#include "src/gpu/GrFragmentProcessor.h"
#include "src/gpu/GrRecordingContextPriv.h"

#if GR_TEST_UTILS

class GrGeometryProcessor;

GrProcessorTestData::GrProcessorTestData(SkRandom* random, GrRecordingContext* context,
                                         int maxTreeDepth, int numViews, const ViewInfo views[])
        : GrProcessorTestData(random, context, maxTreeDepth, numViews, views,
                              /*inputFP=*/nullptr) {}

GrProcessorTestData::GrProcessorTestData(SkRandom* random, GrRecordingContext* context,
                                         int maxTreeDepth, int numViews, const ViewInfo views[],
                                         std::unique_ptr<GrFragmentProcessor> inputFP)
        : fRandom(random)
        , fMaxTreeDepth(maxTreeDepth)
        , fContext(context)
        , fInputFP(std::move(inputFP)) {
    fViews.reset(views, numViews);
    fArena = std::make_unique<SkArenaAlloc>(1000);
}

GrProcessorTestData::~GrProcessorTestData() {}

GrProxyProvider* GrProcessorTestData::proxyProvider() { return fContext->priv().proxyProvider(); }

const GrCaps* GrProcessorTestData::caps() { return fContext->priv().caps(); }

std::unique_ptr<GrFragmentProcessor> GrProcessorTestData::inputFP() {
    if (fCurrentTreeDepth == 0) {
        // At the top level of the tree, provide the input FP from the test data.
        return fInputFP ? fInputFP->clone() : nullptr;
    } else {
        // At deeper levels of recursion, synthesize a random input.
        return GrProcessorUnitTest::MakeChildFP(this);
    }
}

GrProcessorTestData::ViewInfo GrProcessorTestData::randomView() {
    SkASSERT(!fViews.empty());
    return fViews[fRandom->nextULessThan(fViews.count())];
}

GrProcessorTestData::ViewInfo GrProcessorTestData::randomAlphaOnlyView() {
    int numAlphaOnly = 0;
    for (const auto& [v, ct, at] : fViews) {
        if (GrColorTypeIsAlphaOnly(ct)) {
            ++numAlphaOnly;
        }
    }
    SkASSERT(numAlphaOnly);
    int idx = fRandom->nextULessThan(numAlphaOnly);
    for (const auto& [v, ct, at] : fViews) {
        if (GrColorTypeIsAlphaOnly(ct) && !idx--) {
            return {v, ct, at};
        }
    }
    SkUNREACHABLE;
}

template <class ProcessorSmartPtr>
GrProcessorTestFactory<ProcessorSmartPtr>::GrProcessorTestFactory(MakeProc makeProc,
                                                                  const char* name)
        : fMakeProc(makeProc), fName(name) {
    GetFactories()->push_back(this);
}

template <class ProcessorSmartPtr>
ProcessorSmartPtr GrProcessorTestFactory<ProcessorSmartPtr>::Make(GrProcessorTestData* data) {
    VerifyFactoryCount();
    if (GetFactories()->count() == 0) {
        return nullptr;
    }
    uint32_t idx = data->fRandom->nextULessThan(GetFactories()->count());
    return MakeIdx(idx, data);
}

template <class ProcessorSmartPtr>
ProcessorSmartPtr GrProcessorTestFactory<ProcessorSmartPtr>::MakeIdx(int idx,
                                                                     GrProcessorTestData* data) {
    SkASSERT(idx < GetFactories()->count());
    GrProcessorTestFactory<ProcessorSmartPtr>* factory = (*GetFactories())[idx];
    ProcessorSmartPtr processor = factory->fMakeProc(data);
    if (processor == nullptr) {
        SK_ABORT("%s: TestCreate returned null", factory->fName.c_str());
    }
    return processor;
}

template <class ProcessorSmartPtr>
int GrProcessorTestFactory<ProcessorSmartPtr>::Count() {
    return GetFactories()->count();
}

GrXPFactoryTestFactory::GrXPFactoryTestFactory(GetFn* getProc) : fGetProc(getProc) {
    GetFactories()->push_back(this);
}

const GrXPFactory* GrXPFactoryTestFactory::Get(GrProcessorTestData* data) {
    VerifyFactoryCount();
    if (GetFactories()->count() == 0) {
        return nullptr;
    }
    uint32_t idx = data->fRandom->nextRangeU(0, GetFactories()->count() - 1);
    const GrXPFactory* xpf = (*GetFactories())[idx]->fGetProc(data);
    SkASSERT(xpf);
    return xpf;
}

/*
 * Originally these were both in the processor unit test header, but then it seemed to cause linker
 * problems on android.
 */
template <>
SkTArray<GrFragmentProcessorTestFactory*, true>* GrFragmentProcessorTestFactory::GetFactories() {
    static SkTArray<GrFragmentProcessorTestFactory*, true> gFactories;
    return &gFactories;
}

template <>
SkTArray<GrGeometryProcessorTestFactory*, true>* GrGeometryProcessorTestFactory::GetFactories() {
    static SkTArray<GrGeometryProcessorTestFactory*, true> gFactories;
    return &gFactories;
}

SkTArray<GrXPFactoryTestFactory*, true>* GrXPFactoryTestFactory::GetFactories() {
    static SkTArray<GrXPFactoryTestFactory*, true> gFactories;
    return &gFactories;
}

/*
 * To ensure we always have successful static initialization, before creating from the factories
 * we verify the count is as expected.  If a new factory is added, then these numbers must be
 * manually adjusted.
 */
static constexpr int kFPFactoryCount = 34;
static constexpr int kGPFactoryCount = 14;
static constexpr int kXPFactoryCount = 4;

template <> void GrFragmentProcessorTestFactory::VerifyFactoryCount() {
    if (kFPFactoryCount != GetFactories()->count()) {
        SkDebugf("\nExpected %d fragment processor factories, found %d.\n", kFPFactoryCount,
                 GetFactories()->count());
        SK_ABORT("Wrong number of fragment processor factories!");
    }
}

template <> void GrGeometryProcessorTestFactory::VerifyFactoryCount() {
    if (kGPFactoryCount != GetFactories()->count()) {
        SkDebugf("\nExpected %d geometry processor factories, found %d.\n", kGPFactoryCount,
                 GetFactories()->count());
        SK_ABORT("Wrong number of geometry processor factories!");
    }
}

void GrXPFactoryTestFactory::VerifyFactoryCount() {
    if (kXPFactoryCount != GetFactories()->count()) {
        SkDebugf("\nExpected %d xp factory factories, found %d.\n", kXPFactoryCount,
                 GetFactories()->count());
        SK_ABORT("Wrong number of xp factory factories!");
    }
}

std::unique_ptr<GrFragmentProcessor> GrProcessorUnitTest::MakeChildFP(GrProcessorTestData* data) {
    std::unique_ptr<GrFragmentProcessor> fp;

    ++data->fCurrentTreeDepth;
    if (data->fCurrentTreeDepth > data->fMaxTreeDepth) {
        // We've gone too deep, but we can't necessarily return null without risking an assertion.
        // Instead, return a known-simple zero-child FP. This limits the recursion, and the
        // generated FP will be rejected by the numNonNullChildProcessors check below.
        fp = GrFragmentProcessor::MakeColor(SK_PMColor4fTRANSPARENT);
    } else {
        for (;;) {
            fp = GrFragmentProcessorTestFactory::Make(data);
            SkASSERT(fp);
            // If our tree has already reached its max depth, we must reject FPs that have children.
            if (data->fCurrentTreeDepth < data->fMaxTreeDepth ||
                fp->numNonNullChildProcessors() == 0) {
                break;
            }
        }
    }

    --data->fCurrentTreeDepth;
    return fp;
}

std::unique_ptr<GrFragmentProcessor> GrProcessorUnitTest::MakeOptionalChildFP(
        GrProcessorTestData* data) {
    return data->fRandom->nextBool() ? MakeChildFP(data) : nullptr;
}

template class GrProcessorTestFactory<GrGeometryProcessor*>;
template class GrProcessorTestFactory<std::unique_ptr<GrFragmentProcessor>>;

#endif
