Home | History | Annotate | Download | only in tests
      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