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 "SkString.h" 21#include "glsl/GrGLSLFragmentShaderBuilder.h" 22#include "glsl/GrGLSLGeometryProcessor.h" 23#include "glsl/GrGLSLVarying.h" 24#include "ops/GrMeshDrawOp.h" 25 26namespace { 27class Op : public GrMeshDrawOp { 28public: 29 DEFINE_OP_CLASS_ID 30 31 const char* name() const override { return "Dummy Op"; } 32 33 static std::unique_ptr<GrDrawOp> Make(int numAttribs) { 34 return std::unique_ptr<GrDrawOp>(new Op(numAttribs)); 35 } 36 37 FixedFunctionFlags fixedFunctionFlags() const override { 38 return FixedFunctionFlags::kNone; 39 } 40 41 RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override { 42 return RequiresDstTexture::kNo; 43 } 44 45private: 46 Op(int numAttribs) : INHERITED(ClassID()), fNumAttribs(numAttribs) { 47 this->setBounds(SkRect::MakeWH(1.f, 1.f), HasAABloat::kNo, IsZeroArea::kNo); 48 } 49 50 bool onCombineIfPossible(GrOp*, const GrCaps&) override { return false; } 51 52 void onPrepareDraws(Target* target) const override { 53 class GP : public GrGeometryProcessor { 54 public: 55 GP(int numAttribs) { 56 this->initClassID<GP>(); 57 SkASSERT(numAttribs > 1); 58 for (auto i = 0; i < numAttribs; ++i) { 59 fAttribNames.push_back().printf("attr%d", i); 60 } 61 for (auto i = 0; i < numAttribs; ++i) { 62 this->addVertexAttrib(fAttribNames[i].c_str(), kVec2f_GrVertexAttribType); 63 } 64 } 65 const char* name() const override { return "Dummy GP"; } 66 67 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override { 68 class GLSLGP : public GrGLSLGeometryProcessor { 69 public: 70 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { 71 const GP& gp = args.fGP.cast<GP>(); 72 args.fVaryingHandler->emitAttributes(gp); 73 this->setupPosition(args.fVertBuilder, gpArgs, gp.getAttrib(0).fName); 74 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder; 75 fragBuilder->codeAppendf("%s = vec4(1);", args.fOutputColor); 76 fragBuilder->codeAppendf("%s = vec4(1);", args.fOutputCoverage); 77 } 78 void setData(const GrGLSLProgramDataManager& pdman, 79 const GrPrimitiveProcessor& primProc, 80 FPCoordTransformIter&&) override {} 81 }; 82 return new GLSLGP(); 83 } 84 void getGLSLProcessorKey(const GrShaderCaps&, 85 GrProcessorKeyBuilder* builder) const override { 86 builder->add32(this->numAttribs()); 87 } 88 89 private: 90 SkTArray<SkString> fAttribNames; 91 }; 92 sk_sp<GrGeometryProcessor> gp(new GP(fNumAttribs)); 93 QuadHelper helper; 94 size_t vertexStride = gp->getVertexStride(); 95 SkPoint* vertices = reinterpret_cast<SkPoint*>(helper.init(target, vertexStride, 1)); 96 vertices->setRectFan(0.f, 0.f, 1.f, 1.f, vertexStride); 97 helper.recordDraw(target, gp.get(), target->makePipeline(0, &GrProcessorSet::EmptySet())); 98 } 99 100 int fNumAttribs; 101 102 typedef GrMeshDrawOp INHERITED; 103}; 104} 105 106DEF_GPUTEST_FOR_ALL_CONTEXTS(VertexAttributeCount, reporter, ctxInfo) { 107 GrContext* context = ctxInfo.grContext(); 108 109 sk_sp<GrRenderTargetContext> renderTargetContext(context->makeDeferredRenderTargetContext( 110 SkBackingFit::kApprox, 111 1, 1, kRGBA_8888_GrPixelConfig, 112 nullptr)); 113 if (!renderTargetContext) { 114 ERRORF(reporter, "Could not create render target context."); 115 return; 116 } 117 int attribCnt = context->caps()->maxVertexAttributes(); 118 if (!attribCnt) { 119 ERRORF(reporter, "No attributes allowed?!"); 120 return; 121 } 122 context->flush(); 123 context->resetGpuStats(); 124#if GR_GPU_STATS 125 REPORTER_ASSERT(reporter, context->getGpu()->stats()->numDraws() == 0); 126 REPORTER_ASSERT(reporter, context->getGpu()->stats()->numFailedDraws() == 0); 127#endif 128 GrPaint grPaint; 129 // This one should succeed. 130 renderTargetContext->priv().testingOnly_addDrawOp(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_addDrawOp(Op::Make(attribCnt + 1)); 138 context->flush(); 139#if GR_GPU_STATS 140 REPORTER_ASSERT(reporter, context->getGpu()->stats()->numDraws() == 0); 141 REPORTER_ASSERT(reporter, context->getGpu()->stats()->numFailedDraws() == 1); 142#endif 143} 144#endif 145