/*
 * Copyright 2020 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 "src/gpu/GrSurfaceDrawContext.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"

static void run_test(skiatest::Reporter*, GrDirectContext*,
                     GrSurfaceDrawContext*, SkVector a,
                     SkVector b, float expectedCrossProduct);

// This is a GPU test that ensures the SkSL 2d cross() intrinsic returns the correct sign (negative,
// positive, or zero).
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkSLCross, reporter, ctxInfo) {
    GrDirectContext* directContext = ctxInfo.directContext();
    auto rtc = GrSurfaceDrawContext::Make(directContext, GrColorType::kRGBA_8888, nullptr,
                                          SkBackingFit::kExact, {1, 1});
    if (!rtc) {
        ERRORF(reporter, "could not create render target context.");
        return;
    }
    run_test(reporter, directContext, rtc.get(), {3,4}, {5,6}, -2);  // Negative.
    run_test(reporter, directContext, rtc.get(), {3,4}, {-5,-6}, 2);  // Positive.
    run_test(reporter, directContext, rtc.get(), {0, 2.287f}, {0, -7.741f}, 0);  // Zero.
    run_test(reporter, directContext, rtc.get(), {62.17f, 0}, {-43.49f, 0}, 0);  // Zero.
}

namespace {

// Outputs:
//     Green if cross(a,b) > 0
//     Red if cross(a,b) < 0
//     Black if cross(a,b) == 0
class VisualizeCrossProductSignFP : public GrFragmentProcessor {
public:
    VisualizeCrossProductSignFP(SkVector a, SkVector b)
            : GrFragmentProcessor(kTestFP_ClassID, kPreservesOpaqueInput_OptimizationFlag)
            , fA(a), fB(b) {
    }

private:
    const char* name() const override { return "VisualizeCrossProductSignFP"; }
    std::unique_ptr<GrFragmentProcessor> clone() const override {
        return std::unique_ptr<GrFragmentProcessor>(new VisualizeCrossProductSignFP(fA, fB));
    }
    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
    bool onIsEqual(const GrFragmentProcessor&) const override { return true; }

    class Impl : public GrGLSLFragmentProcessor {
        void emitCode(EmitArgs& args) override {
            auto& fp = args.fFp.cast<VisualizeCrossProductSignFP>();
            const char* a, *b;
            fAUniform = args.fUniformHandler->addUniform(&fp, kFragment_GrShaderFlag,
                                                         GrSLType::kFloat2_GrSLType, "a", &a);
            fBUniform = args.fUniformHandler->addUniform(&fp, kFragment_GrShaderFlag,
                                                         GrSLType::kFloat2_GrSLType, "b", &b);
            args.fFragBuilder->codeAppendf(R"(
                    float crossProduct = cross(%s, %s);
                    float2 visualization = clamp(float2(-sign(crossProduct), sign(crossProduct)),
                                                 float2(0), float2(1));
                    return half2(visualization).xy01;)", a, b);
        }
        void onSetData(const GrGLSLProgramDataManager& pdman,
                       const GrFragmentProcessor& processor) override {
            const auto& fp = processor.cast<VisualizeCrossProductSignFP>();
            pdman.set2f(fAUniform, fp.fA.x(), fp.fA.y());
            pdman.set2f(fBUniform, fp.fB.x(), fp.fB.y());
        }
        GrGLSLUniformHandler::UniformHandle fAUniform;
        GrGLSLUniformHandler::UniformHandle fBUniform;
    };

    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new Impl; }
    const SkVector fA, fB;
};

}  // namespace

static void run_test(skiatest::Reporter* reporter, GrDirectContext* directContext,
                     GrSurfaceDrawContext* rtc, SkVector a, SkVector b,
                     float expectedCrossProduct) {
    SkASSERT(rtc->width() == 1);
    SkASSERT(rtc->height() == 1);

    rtc->clear(SkPMColor4f::FromBytes_RGBA(0xbaaaaaad));

    GrPaint crossPaint;
    crossPaint.setColor4f(SK_PMColor4fWHITE);
    crossPaint.setPorterDuffXPFactory(SkBlendMode::kSrcOver);
    crossPaint.setColorFragmentProcessor(std::make_unique<VisualizeCrossProductSignFP>(a, b));
    rtc->drawRect(/*clip=*/nullptr, std::move(crossPaint), GrAA::kNo, SkMatrix::I(),
                  SkRect::MakeWH(1,1));

    GrColor result;
    GrPixmap resultPM(SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kPremul_SkAlphaType),
                      &result,
                      sizeof(GrColor));
    rtc->readPixels(directContext, resultPM, {0, 0});

    SkASSERT(expectedCrossProduct == a.cross(b));
    if (expectedCrossProduct > 0) {
        REPORTER_ASSERT(reporter, result == GrColorPackRGBA(0, 255, 0, 255));  // Green.
    } else if (expectedCrossProduct < 0) {
        REPORTER_ASSERT(reporter, result == GrColorPackRGBA(255, 0, 0, 255));  // Red.
    } else {
        REPORTER_ASSERT(reporter, result == GrColorPackRGBA(0, 0, 0, 255));  // Black.
    }
}
