xref: /third_party/skia/tests/SkSLCross.cpp (revision cb93a386)
1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2020 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#include "tests/Test.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "src/gpu/GrFragmentProcessor.h"
11cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
12cb93a386Sopenharmony_ci#include "src/gpu/v1/SurfaceDrawContext_v1.h"
13cb93a386Sopenharmony_ci
14cb93a386Sopenharmony_cistatic void run_test(skiatest::Reporter*, GrDirectContext*,
15cb93a386Sopenharmony_ci                     skgpu::v1::SurfaceDrawContext*, SkVector a,
16cb93a386Sopenharmony_ci                     SkVector b, float expectedCrossProduct);
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ci// This is a GPU test that ensures the SkSL 2d cross() intrinsic returns the correct sign (negative,
19cb93a386Sopenharmony_ci// positive, or zero).
20cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkSLCross, reporter, ctxInfo) {
21cb93a386Sopenharmony_ci    GrDirectContext* dContext = ctxInfo.directContext();
22cb93a386Sopenharmony_ci    auto sdc = skgpu::v1::SurfaceDrawContext::Make(dContext, GrColorType::kRGBA_8888, nullptr,
23cb93a386Sopenharmony_ci                                                   SkBackingFit::kExact, {1, 1}, SkSurfaceProps());
24cb93a386Sopenharmony_ci    if (!sdc) {
25cb93a386Sopenharmony_ci        ERRORF(reporter, "could not create render target context.");
26cb93a386Sopenharmony_ci        return;
27cb93a386Sopenharmony_ci    }
28cb93a386Sopenharmony_ci    run_test(reporter, dContext, sdc.get(), {3,4}, {5,6}, -2);  // Negative.
29cb93a386Sopenharmony_ci    run_test(reporter, dContext, sdc.get(), {3,4}, {-5,-6}, 2);  // Positive.
30cb93a386Sopenharmony_ci    run_test(reporter, dContext, sdc.get(), {0, 2.287f}, {0, -7.741f}, 0);  // Zero.
31cb93a386Sopenharmony_ci    run_test(reporter, dContext, sdc.get(), {62.17f, 0}, {-43.49f, 0}, 0);  // Zero.
32cb93a386Sopenharmony_ci}
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_cinamespace {
35cb93a386Sopenharmony_ci
36cb93a386Sopenharmony_ci// Outputs:
37cb93a386Sopenharmony_ci//     Green if cross(a,b) > 0
38cb93a386Sopenharmony_ci//     Red if cross(a,b) < 0
39cb93a386Sopenharmony_ci//     Black if cross(a,b) == 0
40cb93a386Sopenharmony_ciclass VisualizeCrossProductSignFP : public GrFragmentProcessor {
41cb93a386Sopenharmony_cipublic:
42cb93a386Sopenharmony_ci    VisualizeCrossProductSignFP(SkVector a, SkVector b)
43cb93a386Sopenharmony_ci            : GrFragmentProcessor(kTestFP_ClassID, kPreservesOpaqueInput_OptimizationFlag)
44cb93a386Sopenharmony_ci            , fA(a), fB(b) {
45cb93a386Sopenharmony_ci    }
46cb93a386Sopenharmony_ci
47cb93a386Sopenharmony_ci    const char* name() const override { return "VisualizeCrossProductSignFP"; }
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci    std::unique_ptr<GrFragmentProcessor> clone() const override {
50cb93a386Sopenharmony_ci        return std::unique_ptr<GrFragmentProcessor>(new VisualizeCrossProductSignFP(fA, fB));
51cb93a386Sopenharmony_ci    }
52cb93a386Sopenharmony_ci
53cb93a386Sopenharmony_ciprivate:
54cb93a386Sopenharmony_ci    void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
55cb93a386Sopenharmony_ci    bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_ci    std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override {
58cb93a386Sopenharmony_ci        class Impl : public ProgramImpl {
59cb93a386Sopenharmony_ci        public:
60cb93a386Sopenharmony_ci            void emitCode(EmitArgs& args) override {
61cb93a386Sopenharmony_ci                auto& fp = args.fFp.cast<VisualizeCrossProductSignFP>();
62cb93a386Sopenharmony_ci                const char *a, *b;
63cb93a386Sopenharmony_ci                fAUniform = args.fUniformHandler->addUniform(&fp, kFragment_GrShaderFlag,
64cb93a386Sopenharmony_ci                                                             GrSLType::kFloat2_GrSLType, "a", &a);
65cb93a386Sopenharmony_ci                fBUniform = args.fUniformHandler->addUniform(&fp, kFragment_GrShaderFlag,
66cb93a386Sopenharmony_ci                                                             GrSLType::kFloat2_GrSLType, "b", &b);
67cb93a386Sopenharmony_ci                args.fFragBuilder->codeAppendf(R"(
68cb93a386Sopenharmony_ci                    float crossProduct = cross(%s, %s);
69cb93a386Sopenharmony_ci                    float2 visualization = clamp(float2(-sign(crossProduct), sign(crossProduct)),
70cb93a386Sopenharmony_ci                                                 float2(0), float2(1));
71cb93a386Sopenharmony_ci                return half2(visualization).xy01;)", a, b);
72cb93a386Sopenharmony_ci            }
73cb93a386Sopenharmony_ci
74cb93a386Sopenharmony_ci        private:
75cb93a386Sopenharmony_ci            void onSetData(const GrGLSLProgramDataManager& pdman,
76cb93a386Sopenharmony_ci                           const GrFragmentProcessor& processor) override {
77cb93a386Sopenharmony_ci                const auto& fp = processor.cast<VisualizeCrossProductSignFP>();
78cb93a386Sopenharmony_ci                pdman.set2f(fAUniform, fp.fA.x(), fp.fA.y());
79cb93a386Sopenharmony_ci                pdman.set2f(fBUniform, fp.fB.x(), fp.fB.y());
80cb93a386Sopenharmony_ci            }
81cb93a386Sopenharmony_ci            GrGLSLUniformHandler::UniformHandle fAUniform;
82cb93a386Sopenharmony_ci            GrGLSLUniformHandler::UniformHandle fBUniform;
83cb93a386Sopenharmony_ci        };
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_ci        return std::make_unique<Impl>();
86cb93a386Sopenharmony_ci    }
87cb93a386Sopenharmony_ci    const SkVector fA, fB;
88cb93a386Sopenharmony_ci};
89cb93a386Sopenharmony_ci
90cb93a386Sopenharmony_ci}  // namespace
91cb93a386Sopenharmony_ci
92cb93a386Sopenharmony_cistatic void run_test(skiatest::Reporter* reporter, GrDirectContext* directContext,
93cb93a386Sopenharmony_ci                     skgpu::v1::SurfaceDrawContext* sdc, SkVector a, SkVector b,
94cb93a386Sopenharmony_ci                     float expectedCrossProduct) {
95cb93a386Sopenharmony_ci    SkASSERT(sdc->width() == 1);
96cb93a386Sopenharmony_ci    SkASSERT(sdc->height() == 1);
97cb93a386Sopenharmony_ci
98cb93a386Sopenharmony_ci    sdc->clear(SkPMColor4f::FromBytes_RGBA(0xbaaaaaad));
99cb93a386Sopenharmony_ci
100cb93a386Sopenharmony_ci    GrPaint crossPaint;
101cb93a386Sopenharmony_ci    crossPaint.setColor4f(SK_PMColor4fWHITE);
102cb93a386Sopenharmony_ci    crossPaint.setPorterDuffXPFactory(SkBlendMode::kSrcOver);
103cb93a386Sopenharmony_ci    crossPaint.setColorFragmentProcessor(std::make_unique<VisualizeCrossProductSignFP>(a, b));
104cb93a386Sopenharmony_ci    sdc->drawRect(/*clip=*/nullptr, std::move(crossPaint), GrAA::kNo, SkMatrix::I(),
105cb93a386Sopenharmony_ci                  SkRect::MakeWH(1,1));
106cb93a386Sopenharmony_ci
107cb93a386Sopenharmony_ci    GrColor result;
108cb93a386Sopenharmony_ci    GrPixmap resultPM(SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kPremul_SkAlphaType),
109cb93a386Sopenharmony_ci                      &result,
110cb93a386Sopenharmony_ci                      sizeof(GrColor));
111cb93a386Sopenharmony_ci    sdc->readPixels(directContext, resultPM, {0, 0});
112cb93a386Sopenharmony_ci
113cb93a386Sopenharmony_ci    SkASSERT(expectedCrossProduct == a.cross(b));
114cb93a386Sopenharmony_ci    if (expectedCrossProduct > 0) {
115cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, result == GrColorPackRGBA(0, 255, 0, 255));  // Green.
116cb93a386Sopenharmony_ci    } else if (expectedCrossProduct < 0) {
117cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, result == GrColorPackRGBA(255, 0, 0, 255));  // Red.
118cb93a386Sopenharmony_ci    } else {
119cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, result == GrColorPackRGBA(0, 0, 0, 255));  // Black.
120cb93a386Sopenharmony_ci    }
121cb93a386Sopenharmony_ci}
122