1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc. 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 "include/core/SkTypes.h" 9cb93a386Sopenharmony_ci#include "tests/Test.h" 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 12cb93a386Sopenharmony_ci#include "include/gpu/GrRecordingContext.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrColor.h" 14cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 15cb93a386Sopenharmony_ci#include "src/gpu/GrGeometryProcessor.h" 16cb93a386Sopenharmony_ci#include "src/gpu/GrImageInfo.h" 17cb93a386Sopenharmony_ci#include "src/gpu/GrMemoryPool.h" 18cb93a386Sopenharmony_ci#include "src/gpu/GrOpFlushState.h" 19cb93a386Sopenharmony_ci#include "src/gpu/GrOpsRenderPass.h" 20cb93a386Sopenharmony_ci#include "src/gpu/GrProgramInfo.h" 21cb93a386Sopenharmony_ci#include "src/gpu/GrRecordingContextPriv.h" 22cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h" 23cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" 24cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLVarying.h" 25cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h" 26cb93a386Sopenharmony_ci#include "src/gpu/ops/GrDrawOp.h" 27cb93a386Sopenharmony_ci#include "src/gpu/v1/SurfaceDrawContext_v1.h" 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ci/** 30cb93a386Sopenharmony_ci * This is a GPU-backend specific test for dynamic pipeline state. It draws boxes using dynamic 31cb93a386Sopenharmony_ci * scissor rectangles then reads back the result to verify a successful test. 32cb93a386Sopenharmony_ci */ 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_cistatic constexpr int kScreenSize = 6; 35cb93a386Sopenharmony_cistatic constexpr int kNumMeshes = 4; 36cb93a386Sopenharmony_cistatic constexpr int kScreenSplitX = kScreenSize/2; 37cb93a386Sopenharmony_cistatic constexpr int kScreenSplitY = kScreenSize/2; 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_cistatic const SkIRect kDynamicScissors[kNumMeshes] = { 40cb93a386Sopenharmony_ci SkIRect::MakeLTRB(0, 0, kScreenSplitX, kScreenSplitY), 41cb93a386Sopenharmony_ci SkIRect::MakeLTRB(0, kScreenSplitY, kScreenSplitX, kScreenSize), 42cb93a386Sopenharmony_ci SkIRect::MakeLTRB(kScreenSplitX, 0, kScreenSize, kScreenSplitY), 43cb93a386Sopenharmony_ci SkIRect::MakeLTRB(kScreenSplitX, kScreenSplitY, kScreenSize, kScreenSize), 44cb93a386Sopenharmony_ci}; 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_cistatic const GrColor kMeshColors[kNumMeshes] { 47cb93a386Sopenharmony_ci GrColorPackRGBA(255, 0, 0, 255), 48cb93a386Sopenharmony_ci GrColorPackRGBA(0, 255, 0, 255), 49cb93a386Sopenharmony_ci GrColorPackRGBA(0, 0, 255, 255), 50cb93a386Sopenharmony_ci GrColorPackRGBA(0, 0, 0, 255) 51cb93a386Sopenharmony_ci}; 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_cistruct Vertex { 54cb93a386Sopenharmony_ci float fX; 55cb93a386Sopenharmony_ci float fY; 56cb93a386Sopenharmony_ci GrColor fColor; 57cb93a386Sopenharmony_ci}; 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_cinamespace { 60cb93a386Sopenharmony_ciclass PipelineDynamicStateTestProcessor : public GrGeometryProcessor { 61cb93a386Sopenharmony_cipublic: 62cb93a386Sopenharmony_ci static GrGeometryProcessor* Make(SkArenaAlloc* arena) { 63cb93a386Sopenharmony_ci return arena->make( 64cb93a386Sopenharmony_ci [&](void* ptr) { return new (ptr) PipelineDynamicStateTestProcessor(); }); 65cb93a386Sopenharmony_ci } 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci const char* name() const override { return "GrPipelineDynamicStateTest Processor"; } 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_ci void addToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const final {} 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const final; 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ciprivate: 74cb93a386Sopenharmony_ci PipelineDynamicStateTestProcessor() : INHERITED(kGrPipelineDynamicStateTestProcessor_ClassID) { 75cb93a386Sopenharmony_ci this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes)); 76cb93a386Sopenharmony_ci } 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci const Attribute& inVertex() const { return kAttributes[0]; } 79cb93a386Sopenharmony_ci const Attribute& inColor() const { return kAttributes[1]; } 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci inline static constexpr Attribute kAttributes[] = { 82cb93a386Sopenharmony_ci {"vertex", kFloat2_GrVertexAttribType, kHalf2_GrSLType}, 83cb93a386Sopenharmony_ci {"color", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType}, 84cb93a386Sopenharmony_ci }; 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ci friend class GLSLPipelineDynamicStateTestProcessor; 87cb93a386Sopenharmony_ci using INHERITED = GrGeometryProcessor; 88cb93a386Sopenharmony_ci}; 89cb93a386Sopenharmony_ci} // anonymous namespace 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_cistd::unique_ptr<GrGeometryProcessor::ProgramImpl> 92cb93a386Sopenharmony_ciPipelineDynamicStateTestProcessor::makeProgramImpl(const GrShaderCaps&) const { 93cb93a386Sopenharmony_ci class Impl : public GrGeometryProcessor::ProgramImpl { 94cb93a386Sopenharmony_ci public: 95cb93a386Sopenharmony_ci void setData(const GrGLSLProgramDataManager&, 96cb93a386Sopenharmony_ci const GrShaderCaps&, 97cb93a386Sopenharmony_ci const GrGeometryProcessor&) final {} 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final { 100cb93a386Sopenharmony_ci const PipelineDynamicStateTestProcessor& mp = 101cb93a386Sopenharmony_ci args.fGeomProc.cast<PipelineDynamicStateTestProcessor>(); 102cb93a386Sopenharmony_ci GrGLSLVertexBuilder* v = args.fVertBuilder; 103cb93a386Sopenharmony_ci GrGLSLFPFragmentBuilder* f = args.fFragBuilder; 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ci GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; 106cb93a386Sopenharmony_ci varyingHandler->emitAttributes(mp); 107cb93a386Sopenharmony_ci f->codeAppendf("half4 %s;", args.fOutputColor); 108cb93a386Sopenharmony_ci varyingHandler->addPassThroughAttribute(mp.inColor().asShaderVar(), args.fOutputColor); 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci v->codeAppendf("float2 vertex = %s;", mp.inVertex().name()); 111cb93a386Sopenharmony_ci gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex"); 112cb93a386Sopenharmony_ci f->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage); 113cb93a386Sopenharmony_ci } 114cb93a386Sopenharmony_ci }; 115cb93a386Sopenharmony_ci return std::make_unique<Impl>(); 116cb93a386Sopenharmony_ci} 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_cinamespace { 119cb93a386Sopenharmony_ciclass GrPipelineDynamicStateTestOp : public GrDrawOp { 120cb93a386Sopenharmony_cipublic: 121cb93a386Sopenharmony_ci DEFINE_OP_CLASS_ID 122cb93a386Sopenharmony_ci 123cb93a386Sopenharmony_ci static GrOp::Owner Make(GrRecordingContext* context, 124cb93a386Sopenharmony_ci GrScissorTest scissorTest, 125cb93a386Sopenharmony_ci sk_sp<const GrBuffer> vbuff) { 126cb93a386Sopenharmony_ci return GrOp::Make<GrPipelineDynamicStateTestOp>(context, scissorTest, std::move(vbuff)); 127cb93a386Sopenharmony_ci } 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ciprivate: 130cb93a386Sopenharmony_ci friend class GrOp; 131cb93a386Sopenharmony_ci 132cb93a386Sopenharmony_ci GrPipelineDynamicStateTestOp(GrScissorTest scissorTest, sk_sp<const GrBuffer> vbuff) 133cb93a386Sopenharmony_ci : INHERITED(ClassID()) 134cb93a386Sopenharmony_ci , fScissorTest(scissorTest) 135cb93a386Sopenharmony_ci , fVertexBuffer(std::move(vbuff)) { 136cb93a386Sopenharmony_ci this->setBounds(SkRect::MakeIWH(kScreenSize, kScreenSize), 137cb93a386Sopenharmony_ci HasAABloat::kNo, IsHairline::kNo); 138cb93a386Sopenharmony_ci } 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci const char* name() const override { return "GrPipelineDynamicStateTestOp"; } 141cb93a386Sopenharmony_ci FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; } 142cb93a386Sopenharmony_ci GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override { 143cb93a386Sopenharmony_ci return GrProcessorSet::EmptySetAnalysis(); 144cb93a386Sopenharmony_ci } 145cb93a386Sopenharmony_ci void onPrePrepare(GrRecordingContext*, 146cb93a386Sopenharmony_ci const GrSurfaceProxyView& writeView, 147cb93a386Sopenharmony_ci GrAppliedClip*, 148cb93a386Sopenharmony_ci const GrDstProxyView&, 149cb93a386Sopenharmony_ci GrXferBarrierFlags renderPassXferBarriers, 150cb93a386Sopenharmony_ci GrLoadOp colorLoadOp) override {} 151cb93a386Sopenharmony_ci void onPrepare(GrOpFlushState*) override {} 152cb93a386Sopenharmony_ci void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override { 153cb93a386Sopenharmony_ci GrPipeline pipeline(fScissorTest, SkBlendMode::kSrc, 154cb93a386Sopenharmony_ci flushState->drawOpArgs().writeView().swizzle()); 155cb93a386Sopenharmony_ci SkSTArray<kNumMeshes, GrSimpleMesh> meshes; 156cb93a386Sopenharmony_ci for (int i = 0; i < kNumMeshes; ++i) { 157cb93a386Sopenharmony_ci GrSimpleMesh& mesh = meshes.push_back(); 158cb93a386Sopenharmony_ci mesh.set(fVertexBuffer, 4, 4 * i); 159cb93a386Sopenharmony_ci } 160cb93a386Sopenharmony_ci 161cb93a386Sopenharmony_ci auto geomProc = PipelineDynamicStateTestProcessor::Make(flushState->allocator()); 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_ci GrProgramInfo programInfo(flushState->caps(), 164cb93a386Sopenharmony_ci flushState->writeView(), 165cb93a386Sopenharmony_ci flushState->usesMSAASurface(), 166cb93a386Sopenharmony_ci &pipeline, 167cb93a386Sopenharmony_ci &GrUserStencilSettings::kUnused, 168cb93a386Sopenharmony_ci geomProc, 169cb93a386Sopenharmony_ci GrPrimitiveType::kTriangleStrip, 0, 170cb93a386Sopenharmony_ci flushState->renderPassBarriers(), 171cb93a386Sopenharmony_ci flushState->colorLoadOp()); 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_ci flushState->bindPipeline(programInfo, SkRect::MakeIWH(kScreenSize, kScreenSize)); 174cb93a386Sopenharmony_ci for (int i = 0; i < 4; ++i) { 175cb93a386Sopenharmony_ci if (fScissorTest == GrScissorTest::kEnabled) { 176cb93a386Sopenharmony_ci flushState->setScissorRect(kDynamicScissors[i]); 177cb93a386Sopenharmony_ci } 178cb93a386Sopenharmony_ci flushState->drawMesh(meshes[i]); 179cb93a386Sopenharmony_ci } 180cb93a386Sopenharmony_ci } 181cb93a386Sopenharmony_ci 182cb93a386Sopenharmony_ci GrScissorTest fScissorTest; 183cb93a386Sopenharmony_ci const sk_sp<const GrBuffer> fVertexBuffer; 184cb93a386Sopenharmony_ci 185cb93a386Sopenharmony_ci using INHERITED = GrDrawOp; 186cb93a386Sopenharmony_ci}; 187cb93a386Sopenharmony_ci} // anonymous namespace 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrPipelineDynamicStateTest, reporter, ctxInfo) { 190cb93a386Sopenharmony_ci auto dContext = ctxInfo.directContext(); 191cb93a386Sopenharmony_ci GrResourceProvider* rp = dContext->priv().resourceProvider(); 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ci auto sdc = skgpu::v1::SurfaceDrawContext::Make( 194cb93a386Sopenharmony_ci dContext, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kExact, 195cb93a386Sopenharmony_ci {kScreenSize, kScreenSize}, SkSurfaceProps()); 196cb93a386Sopenharmony_ci if (!sdc) { 197cb93a386Sopenharmony_ci ERRORF(reporter, "could not create render target context."); 198cb93a386Sopenharmony_ci return; 199cb93a386Sopenharmony_ci } 200cb93a386Sopenharmony_ci 201cb93a386Sopenharmony_ci constexpr float d = (float) kScreenSize; 202cb93a386Sopenharmony_ci Vertex vdata[kNumMeshes * 4] = { 203cb93a386Sopenharmony_ci {0, 0, kMeshColors[0]}, 204cb93a386Sopenharmony_ci {0, d, kMeshColors[0]}, 205cb93a386Sopenharmony_ci {d, 0, kMeshColors[0]}, 206cb93a386Sopenharmony_ci {d, d, kMeshColors[0]}, 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_ci {0, 0, kMeshColors[1]}, 209cb93a386Sopenharmony_ci {0, d, kMeshColors[1]}, 210cb93a386Sopenharmony_ci {d, 0, kMeshColors[1]}, 211cb93a386Sopenharmony_ci {d, d, kMeshColors[1]}, 212cb93a386Sopenharmony_ci 213cb93a386Sopenharmony_ci {0, 0, kMeshColors[2]}, 214cb93a386Sopenharmony_ci {0, d, kMeshColors[2]}, 215cb93a386Sopenharmony_ci {d, 0, kMeshColors[2]}, 216cb93a386Sopenharmony_ci {d, d, kMeshColors[2]}, 217cb93a386Sopenharmony_ci 218cb93a386Sopenharmony_ci {0, 0, kMeshColors[3]}, 219cb93a386Sopenharmony_ci {0, d, kMeshColors[3]}, 220cb93a386Sopenharmony_ci {d, 0, kMeshColors[3]}, 221cb93a386Sopenharmony_ci {d, d, kMeshColors[3]} 222cb93a386Sopenharmony_ci }; 223cb93a386Sopenharmony_ci 224cb93a386Sopenharmony_ci sk_sp<const GrBuffer> vbuff(rp->createBuffer(sizeof(vdata), GrGpuBufferType::kVertex, 225cb93a386Sopenharmony_ci kDynamic_GrAccessPattern, vdata)); 226cb93a386Sopenharmony_ci if (!vbuff) { 227cb93a386Sopenharmony_ci ERRORF(reporter, "vbuff is null."); 228cb93a386Sopenharmony_ci return; 229cb93a386Sopenharmony_ci } 230cb93a386Sopenharmony_ci 231cb93a386Sopenharmony_ci uint32_t resultPx[kScreenSize * kScreenSize]; 232cb93a386Sopenharmony_ci 233cb93a386Sopenharmony_ci for (GrScissorTest scissorTest : {GrScissorTest::kEnabled, GrScissorTest::kDisabled}) { 234cb93a386Sopenharmony_ci sdc->clear(SkPMColor4f::FromBytes_RGBA(0xbaaaaaad)); 235cb93a386Sopenharmony_ci sdc->addDrawOp(GrPipelineDynamicStateTestOp::Make(dContext, scissorTest, vbuff)); 236cb93a386Sopenharmony_ci auto ii = SkImageInfo::Make(kScreenSize, kScreenSize, 237cb93a386Sopenharmony_ci kRGBA_8888_SkColorType, kPremul_SkAlphaType); 238cb93a386Sopenharmony_ci GrPixmap resultPM(ii, resultPx, kScreenSize*sizeof(uint32_t)); 239cb93a386Sopenharmony_ci sdc->readPixels(dContext, resultPM, {0, 0}); 240cb93a386Sopenharmony_ci for (int y = 0; y < kScreenSize; ++y) { 241cb93a386Sopenharmony_ci for (int x = 0; x < kScreenSize; ++x) { 242cb93a386Sopenharmony_ci int expectedColorIdx; 243cb93a386Sopenharmony_ci if (GrScissorTest::kEnabled == scissorTest) { 244cb93a386Sopenharmony_ci expectedColorIdx = (x < kScreenSplitX ? 0 : 2) + (y < kScreenSplitY ? 0 : 1); 245cb93a386Sopenharmony_ci } else { 246cb93a386Sopenharmony_ci expectedColorIdx = kNumMeshes - 1; 247cb93a386Sopenharmony_ci } 248cb93a386Sopenharmony_ci uint32_t expected = kMeshColors[expectedColorIdx]; 249cb93a386Sopenharmony_ci uint32_t actual = resultPx[y * kScreenSize + x]; 250cb93a386Sopenharmony_ci if (expected != actual) { 251cb93a386Sopenharmony_ci ERRORF(reporter, "[scissor=%s] pixel (%i,%i): got 0x%x expected 0x%x", 252cb93a386Sopenharmony_ci GrScissorTest::kEnabled == scissorTest ? "enabled" : "disabled", x, y, 253cb93a386Sopenharmony_ci actual, expected); 254cb93a386Sopenharmony_ci return; 255cb93a386Sopenharmony_ci } 256cb93a386Sopenharmony_ci } 257cb93a386Sopenharmony_ci } 258cb93a386Sopenharmony_ci } 259cb93a386Sopenharmony_ci} 260