1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2021 Google LLC
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci/**
9cb93a386Sopenharmony_ci * This test relies on GLSL ES2 conformance test files, which are not included in Skia.
10cb93a386Sopenharmony_ci *
11cb93a386Sopenharmony_ci * To run the test suite, open `resources/sksl/es2_conformance/import_conformance_tests.py` and
12cb93a386Sopenharmony_ci * follow the instructions at the top to download and import the test suite.
13cb93a386Sopenharmony_ci */
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_ci#include "gm/gm.h"
16cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h"
17cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
18cb93a386Sopenharmony_ci#include "include/core/SkData.h"
19cb93a386Sopenharmony_ci#include "include/core/SkFont.h"
20cb93a386Sopenharmony_ci#include "include/core/SkPaint.h"
21cb93a386Sopenharmony_ci#include "include/core/SkSize.h"
22cb93a386Sopenharmony_ci#include "include/core/SkString.h"
23cb93a386Sopenharmony_ci#include "include/core/SkStringView.h"
24cb93a386Sopenharmony_ci#include "include/core/SkSurface.h"
25cb93a386Sopenharmony_ci#include "include/effects/SkGradientShader.h"
26cb93a386Sopenharmony_ci#include "include/effects/SkImageFilters.h"
27cb93a386Sopenharmony_ci#include "include/effects/SkRuntimeEffect.h"
28cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h"
29cb93a386Sopenharmony_ci#include "src/core/SkOSFile.h"
30cb93a386Sopenharmony_ci#include "src/core/SkRuntimeEffectPriv.h"
31cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h"
32cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
33cb93a386Sopenharmony_ci#include "src/utils/SkOSPath.h"
34cb93a386Sopenharmony_ci#include "tests/Test.h"
35cb93a386Sopenharmony_ci#include "tools/Resources.h"
36cb93a386Sopenharmony_ci#include "tools/ToolUtils.h"
37cb93a386Sopenharmony_ci
38cb93a386Sopenharmony_cistatic void test_expect_fail(skiatest::Reporter* r, const char* testFile) {
39cb93a386Sopenharmony_ci    SkRuntimeEffect::Options options{};
40cb93a386Sopenharmony_ci    sk_sp<SkData> shaderData = GetResourceAsData(testFile);
41cb93a386Sopenharmony_ci    if (!shaderData) {
42cb93a386Sopenharmony_ci        ERRORF(r, "%s: Unable to load file", SkOSPath::Basename(testFile).c_str());
43cb93a386Sopenharmony_ci        return;
44cb93a386Sopenharmony_ci    }
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_ci    SkString shaderString{reinterpret_cast<const char*>(shaderData->bytes()), shaderData->size()};
47cb93a386Sopenharmony_ci    SkRuntimeEffect::Result result = SkRuntimeEffect::MakeForShader(shaderString, options);
48cb93a386Sopenharmony_ci    if (result.effect) {
49cb93a386Sopenharmony_ci        ERRORF(r, "%s: Expected failure, but compiled successfully",
50cb93a386Sopenharmony_ci                  SkOSPath::Basename(testFile).c_str());
51cb93a386Sopenharmony_ci        return;
52cb93a386Sopenharmony_ci    }
53cb93a386Sopenharmony_ci}
54cb93a386Sopenharmony_ci
55cb93a386Sopenharmony_cistatic void test_expect_pass(skiatest::Reporter* r, SkSurface* surface, const char* testFile) {
56cb93a386Sopenharmony_ci    SkRuntimeEffect::Options options{};
57cb93a386Sopenharmony_ci    sk_sp<SkData> shaderData = GetResourceAsData(testFile);
58cb93a386Sopenharmony_ci    if (!shaderData) {
59cb93a386Sopenharmony_ci        ERRORF(r, "%s: Unable to load file", testFile);
60cb93a386Sopenharmony_ci        return;
61cb93a386Sopenharmony_ci    }
62cb93a386Sopenharmony_ci
63cb93a386Sopenharmony_ci    SkString shaderString{reinterpret_cast<const char*>(shaderData->bytes()), shaderData->size()};
64cb93a386Sopenharmony_ci    SkRuntimeEffect::Result result = SkRuntimeEffect::MakeForShader(shaderString, options);
65cb93a386Sopenharmony_ci    if (!result.effect) {
66cb93a386Sopenharmony_ci        ERRORF(r, "%s: %s", testFile, result.errorText.c_str());
67cb93a386Sopenharmony_ci        return;
68cb93a386Sopenharmony_ci    }
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci    SkRuntimeShaderBuilder builder(result.effect);
71cb93a386Sopenharmony_ci    sk_sp<SkShader> shader = builder.makeShader(/*localMatrix=*/nullptr, /*isOpaque=*/true);
72cb93a386Sopenharmony_ci    if (!shader) {
73cb93a386Sopenharmony_ci        ERRORF(r, "%s: Unable to build shader", testFile);
74cb93a386Sopenharmony_ci        return;
75cb93a386Sopenharmony_ci    }
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_ci    SkPaint paintShader;
78cb93a386Sopenharmony_ci    paintShader.setShader(shader);
79cb93a386Sopenharmony_ci    surface->getCanvas()->drawRect(SkRect::MakeWH(1, 1), paintShader);
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci    SkBitmap bitmap;
82cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, bitmap.tryAllocPixels(surface->imageInfo()));
83cb93a386Sopenharmony_ci    REPORTER_ASSERT(r, surface->readPixels(bitmap.info(), bitmap.getPixels(), bitmap.rowBytes(),
84cb93a386Sopenharmony_ci                                           /*srcX=*/0, /*srcY=*/0));
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ci    SkColor color = bitmap.getColor(0, 0);
87cb93a386Sopenharmony_ci    if (color != SkColorSetARGB(0xFF, 0x00, 0xFF, 0x00)) {
88cb93a386Sopenharmony_ci        ERRORF(r, "%s: Expected solid green. Actual:\n"
89cb93a386Sopenharmony_ci                  "RRGGBBAA\n"
90cb93a386Sopenharmony_ci                  "%02X%02X%02X%02X",
91cb93a386Sopenharmony_ci                  testFile,
92cb93a386Sopenharmony_ci                  SkColorGetR(color), SkColorGetG(color), SkColorGetB(color), SkColorGetA(color));
93cb93a386Sopenharmony_ci    }
94cb93a386Sopenharmony_ci}
95cb93a386Sopenharmony_ci
96cb93a386Sopenharmony_cistatic void iterate_dir(const char* directory, const std::function<void(const char*)>& run) {
97cb93a386Sopenharmony_ci    SkString resourceDirectory = GetResourcePath(directory);
98cb93a386Sopenharmony_ci    SkOSFile::Iter iter(resourceDirectory.c_str(), ".rts");
99cb93a386Sopenharmony_ci    SkString name;
100cb93a386Sopenharmony_ci
101cb93a386Sopenharmony_ci    while (iter.next(&name, /*getDir=*/false)) {
102cb93a386Sopenharmony_ci        SkString path(SkOSPath::Join(directory, name.c_str()));
103cb93a386Sopenharmony_ci        run(path.c_str());
104cb93a386Sopenharmony_ci    }
105cb93a386Sopenharmony_ci}
106cb93a386Sopenharmony_ci
107cb93a386Sopenharmony_ciDEF_TEST(SkSL_ES2Conformance_Pass_CPU, r) {
108cb93a386Sopenharmony_ci    const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
109cb93a386Sopenharmony_ci    sk_sp<SkSurface> surface(SkSurface::MakeRaster(info));
110cb93a386Sopenharmony_ci
111cb93a386Sopenharmony_ci    iterate_dir("sksl/es2_conformance/pass/", [&](const char* path) {
112cb93a386Sopenharmony_ci        test_expect_pass(r, surface.get(), path);
113cb93a386Sopenharmony_ci    });
114cb93a386Sopenharmony_ci}
115cb93a386Sopenharmony_ci
116cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkSL_ES2Conformance_Pass_GPU, r, ctxInfo) {
117cb93a386Sopenharmony_ci    const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
118cb93a386Sopenharmony_ci    sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(ctxInfo.directContext(),
119cb93a386Sopenharmony_ci                                                         SkBudgeted::kNo, info));
120cb93a386Sopenharmony_ci    iterate_dir("sksl/es2_conformance/pass/", [&](const char* path) {
121cb93a386Sopenharmony_ci        test_expect_pass(r, surface.get(), path);
122cb93a386Sopenharmony_ci    });
123cb93a386Sopenharmony_ci}
124cb93a386Sopenharmony_ci
125cb93a386Sopenharmony_ciDEF_TEST(SkSL_ES2Conformance_Fail, r) {
126cb93a386Sopenharmony_ci    iterate_dir("sksl/es2_conformance/fail/", [&](const char* path) {
127cb93a386Sopenharmony_ci        test_expect_fail(r, path);
128cb93a386Sopenharmony_ci    });
129cb93a386Sopenharmony_ci}
130