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