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

/**
 * This test relies on GLSL ES2 conformance test files, which are not included in Skia.
 *
 * To run the test suite, open `resources/sksl/es2_conformance/import_conformance_tests.py` and
 * follow the instructions at the top to download and import the test suite.
 */

#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkData.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkShader.h"
#include "include/core/SkString.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkRuntimeEffect.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "src/core/SkOSFile.h"
#include "src/utils/SkOSPath.h"
#include "tests/CtsEnforcement.h"
#include "tests/Test.h"
#include "tools/Resources.h"

#include <functional>

struct GrContextOptions;

static void test_expect_fail(skiatest::Reporter* r, const char* testFile) {
    SkRuntimeEffect::Options options{};
    sk_sp<SkData> shaderData = GetResourceAsData(testFile);
    if (!shaderData) {
        ERRORF(r, "%s: Unable to load file", SkOSPath::Basename(testFile).c_str());
        return;
    }

    SkString shaderString{reinterpret_cast<const char*>(shaderData->bytes()), shaderData->size()};
    SkRuntimeEffect::Result result = SkRuntimeEffect::MakeForShader(shaderString, options);
    if (result.effect) {
        ERRORF(r, "%s: Expected failure, but compiled successfully",
                  SkOSPath::Basename(testFile).c_str());
        return;
    }
}

static void test_expect_pass(skiatest::Reporter* r, SkSurface* surface, const char* testFile) {
    SkRuntimeEffect::Options options{};
    sk_sp<SkData> shaderData = GetResourceAsData(testFile);
    if (!shaderData) {
        ERRORF(r, "%s: Unable to load file", testFile);
        return;
    }

    SkString shaderString{reinterpret_cast<const char*>(shaderData->bytes()), shaderData->size()};
    SkRuntimeEffect::Result result = SkRuntimeEffect::MakeForShader(shaderString, options);
    if (!result.effect) {
        ERRORF(r, "%s: %s", testFile, result.errorText.c_str());
        return;
    }

    SkRuntimeShaderBuilder builder(result.effect);
    sk_sp<SkShader> shader = builder.makeShader();
    if (!shader) {
        ERRORF(r, "%s: Unable to build shader", testFile);
        return;
    }

    SkPaint paintShader;
    paintShader.setShader(shader);
    surface->getCanvas()->drawRect(SkRect::MakeWH(1, 1), paintShader);

    SkBitmap bitmap;
    REPORTER_ASSERT(r, bitmap.tryAllocPixels(surface->imageInfo()));
    REPORTER_ASSERT(r, surface->readPixels(bitmap.info(), bitmap.getPixels(), bitmap.rowBytes(),
                                           /*srcX=*/0, /*srcY=*/0));

    SkColor color = bitmap.getColor(0, 0);
    if (color != SkColorSetARGB(0xFF, 0x00, 0xFF, 0x00)) {
        ERRORF(r, "%s: Expected solid green. Actual:\n"
                  "RRGGBBAA\n"
                  "%02X%02X%02X%02X",
                  testFile,
                  SkColorGetR(color), SkColorGetG(color), SkColorGetB(color), SkColorGetA(color));
    }
}

static void iterate_dir(const char* directory, const std::function<void(const char*)>& run) {
    SkString resourceDirectory = GetResourcePath(directory);
    SkOSFile::Iter iter(resourceDirectory.c_str(), ".rts");
    SkString name;

    while (iter.next(&name, /*getDir=*/false)) {
        SkString path(SkOSPath::Join(directory, name.c_str()));
        run(path.c_str());
    }
}

DEF_TEST(SkSL_ES2Conformance_Pass_CPU, r) {
    const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
    sk_sp<SkSurface> surface(SkSurfaces::Raster(info));

    iterate_dir("sksl/es2_conformance/pass/", [&](const char* path) {
        test_expect_pass(r, surface.get(), path);
    });
}

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkSL_ES2Conformance_Pass_GPU,
                                       r,
                                       ctxInfo,
                                       CtsEnforcement::kApiLevel_T) {
    const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
    sk_sp<SkSurface> surface(
            SkSurfaces::RenderTarget(ctxInfo.directContext(), skgpu::Budgeted::kNo, info));
    iterate_dir("sksl/es2_conformance/pass/", [&](const char* path) {
        test_expect_pass(r, surface.get(), path);
    });
}

DEF_TEST(SkSL_ES2Conformance_Fail, r) {
    iterate_dir("sksl/es2_conformance/fail/", [&](const char* path) {
        test_expect_fail(r, path);
    });
}
