Index: tests/PrimitiveProcessorTest.cpp |
diff --git a/tests/PrimitiveProcessorTest.cpp b/tests/PrimitiveProcessorTest.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..922b4fd89232799d7b51d809befc1c9ef01f9191 |
--- /dev/null |
+++ b/tests/PrimitiveProcessorTest.cpp |
@@ -0,0 +1,155 @@ |
+ |
+/* |
+ * Copyright 2016 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+// This is a GPU-backend specific test. It relies on static intializers to work |
+ |
+#include "SkTypes.h" |
+#include "Test.h" |
+ |
+#if SK_SUPPORT_GPU |
+#include "GrBatchFlushState.h" |
+#include "GrDrawContext.h" |
+#include "GrDrawContextPriv.h" |
+#include "GrContext.h" |
+#include "GrGeometryProcessor.h" |
+#include "GrGpu.h" |
+#include "GrTextureProvider.h" |
+#include "glsl/GrGLSLGeometryProcessor.h" |
+#include "glsl/GrGLSLVarying.h" |
+#include "batches/GrVertexBatch.h" |
+#include "SkString.h" |
+ |
+namespace { |
+class Batch : public GrVertexBatch { |
+public: |
+ DEFINE_BATCH_CLASS_ID |
+ |
+ const char* name() const override { return "Dummy Batch"; } |
+ void computePipelineOptimizations(GrInitInvariantOutput* color, |
+ GrInitInvariantOutput* coverage, |
+ GrBatchToXPOverrides* overrides) const override { |
+ color->setUnknownFourComponents(); |
+ coverage->setUnknownSingleComponent(); |
+ } |
+ |
+ void initBatchTracker(const GrXPOverridesForBatch& overrides) override {} |
+ |
+ Batch(int numAttribs) |
+ : INHERITED(ClassID()) |
+ , fNumAttribs(numAttribs) { |
+ this->setBounds(SkRect::MakeWH(1.f, 1.f)); |
+ } |
+ |
+private: |
+ bool onCombineIfPossible(GrBatch*, const GrCaps&) override { return false; } |
+ void onPrepareDraws(Target* target) const override { |
+ class GP : public GrGeometryProcessor { |
+ public: |
+ GP(int numAttribs) { |
+ this->initClassID<GP>(); |
+ SkASSERT(numAttribs > 1); |
+ for (auto i = 0; i < numAttribs; ++i) { |
+ fAttribNames.push_back().printf("attr%d", i); |
+ } |
+ for (auto i = 0; i < numAttribs; ++i) { |
+ Attribute attribute; |
+ attribute.fType = kVec2f_GrVertexAttribType; |
+ attribute.fName = fAttribNames[i].c_str(); |
+ attribute.fOffset = 2 * sizeof(float) * i; |
+ attribute.fPrecision = kDefault_GrSLPrecision; |
+ this->addVertexAttrib(attribute); |
+ } |
+ }; |
+ const char* name() const override { return "Dummy GP"; } |
+ |
+ GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const override { |
+ class GLSLGP : public GrGLSLGeometryProcessor { |
+ public: |
+ void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { |
+ const GP& gp = args.fGP.cast<GP>(); |
+ args.fVaryingHandler->emitAttributes(gp); |
+ this->setupPosition(args.fVertBuilder, gpArgs, gp.fAttribs[0].fName); |
+ } |
+ void setData(const GrGLSLProgramDataManager& pdman, |
+ const GrPrimitiveProcessor& primProc) override {} |
+ }; |
+ return new GLSLGP(); |
+ } |
+ void getGLSLProcessorKey(const GrGLSLCaps&, |
+ GrProcessorKeyBuilder* builder) const override { |
+ builder->add32(this->numAttribs()); |
+ } |
+ |
+ private: |
+ SkTArray<SkString> fAttribNames; |
+ }; |
+ SkAutoTUnref<GrGeometryProcessor> gp(new GP(fNumAttribs)); |
+ target->initDraw(gp); |
+ QuadHelper helper; |
+ size_t vertexStride = gp->getVertexStride(); |
+ SkPoint* vertices = reinterpret_cast<SkPoint*>(helper.init(target, vertexStride, 1)); |
+ vertices->setRectFan(0.f, 0.f, 1.f, 1.f, vertexStride); |
+ helper.recordDraw(target); |
+ } |
+ |
+ int fNumAttribs; |
+ |
+ typedef GrVertexBatch INHERITED; |
+}; |
+} |
+ |
+DEF_GPUTEST_FOR_ALL_CONTEXTS(VertexAttributeCount, reporter, context) { |
+ GrTextureDesc desc; |
+ desc.fHeight = 1; |
+ desc.fWidth = 1; |
+ desc.fFlags = kRenderTarget_GrSurfaceFlag; |
+ desc.fConfig = kRGBA_8888_GrPixelConfig; |
+ SkAutoTUnref<GrTexture> target(context->textureProvider()->createTexture(desc, |
+ SkBudgeted::kYes)); |
+ if (!target) { |
+ ERRORF(reporter, "Could not create render target."); |
+ return; |
+ } |
+ SkAutoTUnref<GrDrawContext> dc(context->drawContext(target->asRenderTarget())); |
+ if (!dc) { |
+ ERRORF(reporter, "Could not create draw context."); |
+ return; |
+ } |
+ int attribCnt = context->caps()->maxVertexAttributes(); |
+ if (!attribCnt) { |
+ ERRORF(reporter, "No attributes allowed?!"); |
+ return; |
+ } |
+ context->flush(); |
+ context->resetGpuStats(); |
+#if GR_GPU_STATS |
+ REPORTER_ASSERT(reporter, context->getGpu()->stats()->numDraws() == 0); |
+ REPORTER_ASSERT(reporter, context->getGpu()->stats()->numFailedDraws() == 0); |
+#endif |
+ SkAutoTUnref<GrDrawBatch> batch; |
+ GrPipelineBuilder pb; |
+ pb.setRenderTarget(target->asRenderTarget()); |
+ // This one should succeed. |
+ batch.reset(new Batch(attribCnt)); |
+ dc->drawContextPriv().testingOnly_drawBatch(pb, batch); |
+ context->flush(); |
+#if GR_GPU_STATS |
+ REPORTER_ASSERT(reporter, context->getGpu()->stats()->numDraws() == 1); |
+ REPORTER_ASSERT(reporter, context->getGpu()->stats()->numFailedDraws() == 0); |
+#endif |
+ context->resetGpuStats(); |
+ // This one should fail. |
+ batch.reset(new Batch(attribCnt+1)); |
+ dc->drawContextPriv().testingOnly_drawBatch(pb, batch); |
+ context->flush(); |
+#if GR_GPU_STATS |
+ REPORTER_ASSERT(reporter, context->getGpu()->stats()->numDraws() == 0); |
+ REPORTER_ASSERT(reporter, context->getGpu()->stats()->numFailedDraws() == 1); |
+#endif |
+} |
+#endif |