1 /* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 // This is a GPU-backend specific test. It relies on static intializers to work 9 10 #include "SkTypes.h" 11 #include "Test.h" 12 13 #if SK_SUPPORT_GPU 14 #include "GrContext.h" 15 #include "GrGeometryProcessor.h" 16 #include "GrGpu.h" 17 #include "GrOpFlushState.h" 18 #include "GrRenderTargetContext.h" 19 #include "GrRenderTargetContextPriv.h" 20 #include "GrResourceProvider.h" 21 #include "SkString.h" 22 #include "glsl/GrGLSLFragmentShaderBuilder.h" 23 #include "glsl/GrGLSLGeometryProcessor.h" 24 #include "glsl/GrGLSLVarying.h" 25 #include "ops/GrMeshDrawOp.h" 26 27 namespace { 28 class Op : public GrMeshDrawOp { 29 public: 30 DEFINE_OP_CLASS_ID 31 32 const char* name() const override { return "Dummy Op"; } 33 34 static std::unique_ptr<GrMeshDrawOp> Make(int numAttribs) { 35 return std::unique_ptr<GrMeshDrawOp>(new Op(numAttribs)); 36 } 37 38 private: 39 Op(int numAttribs) : INHERITED(ClassID()), fNumAttribs(numAttribs) { 40 this->setBounds(SkRect::MakeWH(1.f, 1.f), HasAABloat::kNo, IsZeroArea::kNo); 41 } 42 43 void getFragmentProcessorAnalysisInputs(GrPipelineAnalysisColor* color, 44 GrPipelineAnalysisCoverage* coverage) const override { 45 color->setToUnknown(); 46 *coverage = GrPipelineAnalysisCoverage::kSingleChannel; 47 } 48 49 void applyPipelineOptimizations(const GrPipelineOptimizations&) override {} 50 bool onCombineIfPossible(GrOp*, const GrCaps&) override { return false; } 51 void onPrepareDraws(Target* target) const override { 52 class GP : public GrGeometryProcessor { 53 public: 54 GP(int numAttribs) { 55 this->initClassID<GP>(); 56 SkASSERT(numAttribs > 1); 57 for (auto i = 0; i < numAttribs; ++i) { 58 fAttribNames.push_back().printf("attr%d", i); 59 } 60 for (auto i = 0; i < numAttribs; ++i) { 61 this->addVertexAttrib(fAttribNames[i].c_str(), kVec2f_GrVertexAttribType); 62 } 63 } 64 const char* name() const override { return "Dummy GP"; } 65 66 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override { 67 class GLSLGP : public GrGLSLGeometryProcessor { 68 public: 69 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { 70 const GP& gp = args.fGP.cast<GP>(); 71 args.fVaryingHandler->emitAttributes(gp); 72 this->setupPosition(args.fVertBuilder, gpArgs, gp.fAttribs[0].fName); 73 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; 74 fragBuilder->codeAppendf("%s = vec4(1);", args.fOutputColor); 75 fragBuilder->codeAppendf("%s = vec4(1);", args.fOutputCoverage); 76 } 77 void setData(const GrGLSLProgramDataManager& pdman, 78 const GrPrimitiveProcessor& primProc, 79 FPCoordTransformIter&&) override {} 80 }; 81 return new GLSLGP(); 82 } 83 void getGLSLProcessorKey(const GrShaderCaps&, 84 GrProcessorKeyBuilder* builder) const override { 85 builder->add32(this->numAttribs()); 86 } 87 88 private: 89 SkTArray<SkString> fAttribNames; 90 }; 91 sk_sp<GrGeometryProcessor> gp(new GP(fNumAttribs)); 92 QuadHelper helper; 93 size_t vertexStride = gp->getVertexStride(); 94 SkPoint* vertices = reinterpret_cast<SkPoint*>(helper.init(target, vertexStride, 1)); 95 vertices->setRectFan(0.f, 0.f, 1.f, 1.f, vertexStride); 96 helper.recordDraw(target, gp.get()); 97 } 98 99 int fNumAttribs; 100 101 typedef GrMeshDrawOp INHERITED; 102 }; 103 } 104 105 DEF_GPUTEST_FOR_ALL_CONTEXTS(VertexAttributeCount, reporter, ctxInfo) { 106 GrContext* context = ctxInfo.grContext(); 107 108 sk_sp<GrRenderTargetContext> renderTargetContext(context->makeRenderTargetContext( 109 SkBackingFit::kApprox, 110 1, 1, kRGBA_8888_GrPixelConfig, 111 nullptr)); 112 if (!renderTargetContext) { 113 ERRORF(reporter, "Could not create render target context."); 114 return; 115 } 116 int attribCnt = context->caps()->maxVertexAttributes(); 117 if (!attribCnt) { 118 ERRORF(reporter, "No attributes allowed?!"); 119 return; 120 } 121 context->flush(); 122 context->resetGpuStats(); 123 #if GR_GPU_STATS 124 REPORTER_ASSERT(reporter, context->getGpu()->stats()->numDraws() == 0); 125 REPORTER_ASSERT(reporter, context->getGpu()->stats()->numFailedDraws() == 0); 126 #endif 127 GrPaint grPaint; 128 // This one should succeed. 129 renderTargetContext->priv().testingOnly_addMeshDrawOp(GrPaint(grPaint), GrAAType::kNone, 130 Op::Make(attribCnt)); 131 context->flush(); 132 #if GR_GPU_STATS 133 REPORTER_ASSERT(reporter, context->getGpu()->stats()->numDraws() == 1); 134 REPORTER_ASSERT(reporter, context->getGpu()->stats()->numFailedDraws() == 0); 135 #endif 136 context->resetGpuStats(); 137 renderTargetContext->priv().testingOnly_addMeshDrawOp(std::move(grPaint), GrAAType::kNone, 138 Op::Make(attribCnt + 1)); 139 context->flush(); 140 #if GR_GPU_STATS 141 REPORTER_ASSERT(reporter, context->getGpu()->stats()->numDraws() == 0); 142 REPORTER_ASSERT(reporter, context->getGpu()->stats()->numFailedDraws() == 1); 143 #endif 144 } 145 #endif 146