diff options
-rw-r--r-- | include/gpu/GrProcessorUnitTest.h | 11 | ||||
-rw-r--r-- | src/gpu/effects/GrConstColorProcessor.cpp | 6 | ||||
-rw-r--r-- | src/gpu/effects/GrExtractAlphaFragmentProcessor.cpp | 10 | ||||
-rw-r--r-- | src/gpu/effects/GrXfermodeFragmentProcessor.cpp | 25 | ||||
-rw-r--r-- | tests/GLProgramsTest.cpp | 90 |
5 files changed, 123 insertions, 19 deletions
diff --git a/include/gpu/GrProcessorUnitTest.h b/include/gpu/GrProcessorUnitTest.h index 66ba239602..8a17521bfc 100644 --- a/include/gpu/GrProcessorUnitTest.h +++ b/include/gpu/GrProcessorUnitTest.h @@ -68,10 +68,19 @@ public: GetFactories()->push_back(this); } - static const Processor* CreateStage(GrProcessorTestData* data) { + /** Pick a random factory function and create a processor. */ + static const Processor* Create(GrProcessorTestData* data) { VerifyFactoryCount(); SkASSERT(GetFactories()->count()); uint32_t idx = data->fRandom->nextRangeU(0, GetFactories()->count() - 1); + return CreateIdx(idx, data); + } + + /** Number of registered factory functions */ + static int Count() { return GetFactories()->count(); } + + /** Use factory function at Index idx to create a processor. */ + static const Processor* CreateIdx(int idx, GrProcessorTestData* data) { GrProcessorTestFactory<Processor>* factory = (*GetFactories())[idx]; return factory->fCreateProc(data); } diff --git a/src/gpu/effects/GrConstColorProcessor.cpp b/src/gpu/effects/GrConstColorProcessor.cpp index 95a4081d4f..627139fa41 100644 --- a/src/gpu/effects/GrConstColorProcessor.cpp +++ b/src/gpu/effects/GrConstColorProcessor.cpp @@ -19,7 +19,11 @@ public: fColorUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec4f_GrSLType, kMedium_GrSLPrecision, "constantColor", &colorUni); - switch (args.fFp.cast<GrConstColorProcessor>().inputMode()) { + GrConstColorProcessor::InputMode mode = args.fFp.cast<GrConstColorProcessor>().inputMode(); + if (!args.fInputColor) { + mode = GrConstColorProcessor::kIgnore_InputMode; + } + switch (mode) { case GrConstColorProcessor::kIgnore_InputMode: fsBuilder->codeAppendf("%s = %s;", args.fOutputColor, colorUni); break; diff --git a/src/gpu/effects/GrExtractAlphaFragmentProcessor.cpp b/src/gpu/effects/GrExtractAlphaFragmentProcessor.cpp index c5ee9b8571..8f6af65ca7 100644 --- a/src/gpu/effects/GrExtractAlphaFragmentProcessor.cpp +++ b/src/gpu/effects/GrExtractAlphaFragmentProcessor.cpp @@ -14,9 +14,13 @@ public: GLExtractAlphaFragmentProcessor() {} void emitCode(EmitArgs& args) override { - GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); - fsBuilder->codeAppendf("vec4 alpha4 = %s.aaaa;", args.fInputColor); - this->emitChild(0, "alpha4", args.fOutputColor, args); + if (args.fInputColor) { + GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); + fsBuilder->codeAppendf("vec4 alpha4 = %s.aaaa;", args.fInputColor); + this->emitChild(0, "alpha4", args.fOutputColor, args); + } else { + this->emitChild(0, nullptr, args.fOutputColor, args); + } } private: diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp index 3cb56d07f7..c039db3433 100644 --- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp +++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp @@ -78,12 +78,12 @@ const GrFragmentProcessor* GrComposeTwoFragmentProcessor::TestCreate(GrProcessor // possibility of an arbitrarily large tree of procs. SkAutoTUnref<const GrFragmentProcessor> fpA; do { - fpA.reset(GrProcessorTestFactory<GrFragmentProcessor>::CreateStage(d)); + fpA.reset(GrProcessorTestFactory<GrFragmentProcessor>::Create(d)); SkASSERT(fpA); } while (fpA->numChildProcessors() != 0); SkAutoTUnref<const GrFragmentProcessor> fpB; do { - fpB.reset(GrProcessorTestFactory<GrFragmentProcessor>::CreateStage(d)); + fpB.reset(GrProcessorTestFactory<GrFragmentProcessor>::Create(d)); SkASSERT(fpB); } while (fpB->numChildProcessors() != 0); @@ -112,20 +112,26 @@ void GrGLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) { // This is because we don't want the paint's alpha to affect either child proc's output // before the blend; we want to apply the paint's alpha AFTER the blend. This mirrors the // software implementation of SkComposeShader. - SkString inputAlpha("inputAlpha"); - fsBuilder->codeAppendf("float %s = %s.a;", inputAlpha.c_str(), args.fInputColor); - fsBuilder->codeAppendf("%s /= %s.a;", args.fInputColor, args.fInputColor); + const char* opaqueInput = nullptr; + const char* inputAlpha = nullptr; + if (args.fInputColor) { + inputAlpha = "inputAlpha"; + opaqueInput = "opaqueInput"; + fsBuilder->codeAppendf("float inputAlpha = %s.a;", args.fInputColor); + fsBuilder->codeAppendf("vec4 opaqueInput = vec4(%s.rgb / inputAlpha, 1);", + args.fInputColor); + } // declare outputColor and emit the code for each of the two children SkString outputColorSrc(args.fOutputColor); outputColorSrc.append("_src"); fsBuilder->codeAppendf("vec4 %s;\n", outputColorSrc.c_str()); - this->emitChild(0, args.fInputColor, outputColorSrc.c_str(), args); + this->emitChild(0, opaqueInput, outputColorSrc.c_str(), args); SkString outputColorDst(args.fOutputColor); outputColorDst.append("_dst"); fsBuilder->codeAppendf("vec4 %s;\n", outputColorDst.c_str()); - this->emitChild(1, args.fInputColor, outputColorDst.c_str(), args); + this->emitChild(1, opaqueInput, outputColorDst.c_str(), args); // emit blend code SkXfermode::Mode mode = cs.getMode(); @@ -136,10 +142,11 @@ void GrGLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) { fsBuilder->codeAppend("}"); // re-multiply the output color by the input color's alpha - fsBuilder->codeAppendf("%s *= %s;", args.fOutputColor, inputAlpha.c_str()); + if (inputAlpha) { + fsBuilder->codeAppendf("%s *= %s;", args.fOutputColor, inputAlpha); + } } - const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromTwoProcessors( const GrFragmentProcessor* src, const GrFragmentProcessor* dst, SkXfermode::Mode mode) { if (SkXfermode::kLastCoeffMode < mode) { diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index ce86c9bf38..ba64a7c9cb 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -47,7 +47,11 @@ public: virtual void emitCode(EmitArgs& args) override { // pass through GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); - fsBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, args.fInputColor); + if (args.fInputColor) { + fsBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, args.fInputColor); + } else { + fsBuilder->codeAppendf("%s = vec4(1.0);\n", args.fOutputColor); + } } static void GenKey(const GrProcessor& processor, const GrGLSLCaps&, GrProcessorKeyBuilder* b) { @@ -95,6 +99,49 @@ const GrFragmentProcessor* BigKeyProcessor::TestCreate(GrProcessorTestData*) { return BigKeyProcessor::Create(); } +////////////////////////////////////////////////////////////////////////////// + +class BlockInputFragmentProcessor : public GrFragmentProcessor { +public: + static GrFragmentProcessor* Create(const GrFragmentProcessor* fp) { + return new BlockInputFragmentProcessor(fp); + } + + const char* name() const override { return "Block Input"; } + + GrGLFragmentProcessor* onCreateGLInstance() const override { return new GLFP; } + +private: + class GLFP : public GrGLFragmentProcessor { + public: + void emitCode(EmitArgs& args) override { + this->emitChild(0, nullptr, args.fOutputColor, args); + } + + private: + typedef GrGLFragmentProcessor INHERITED; + }; + + BlockInputFragmentProcessor(const GrFragmentProcessor* child) { + this->initClassID<BlockInputFragmentProcessor>(); + this->registerChildProcessor(child); + } + + void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {} + + bool onIsEqual(const GrFragmentProcessor&) const override { return true; } + + void onComputeInvariantOutput(GrInvariantOutput* inout) const override { + inout->setToOther(kRGBA_GrColorComponentFlags, GrColor_WHITE, + GrInvariantOutput::kWillNot_ReadInput); + this->childProcessor(0).computeInvariantOutput(inout); + } + + typedef GrFragmentProcessor INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + /* * Begin test code */ @@ -132,7 +179,7 @@ static GrRenderTarget* random_render_target(GrTextureProvider* textureProvider, } static void set_random_xpf(GrPipelineBuilder* pipelineBuilder, GrProcessorTestData* d) { - SkAutoTUnref<const GrXPFactory> xpf(GrProcessorTestFactory<GrXPFactory>::CreateStage(d)); + SkAutoTUnref<const GrXPFactory> xpf(GrProcessorTestFactory<GrXPFactory>::Create(d)); SkASSERT(xpf); pipelineBuilder->setXPFactory(xpf.get()); } @@ -151,7 +198,7 @@ static const GrFragmentProcessor* create_random_proc_tree(GrProcessorTestData* d if (terminate) { const GrFragmentProcessor* fp; while (true) { - fp = GrProcessorTestFactory<GrFragmentProcessor>::CreateStage(d); + fp = GrProcessorTestFactory<GrFragmentProcessor>::Create(d); SkASSERT(fp); if (0 == fp->numChildProcessors()) { break; @@ -201,7 +248,7 @@ static void set_random_color_coverage_stages(GrPipelineBuilder* pipelineBuilder, for (int s = 0; s < numProcs;) { SkAutoTUnref<const GrFragmentProcessor> fp( - GrProcessorTestFactory<GrFragmentProcessor>::CreateStage(d)); + GrProcessorTestFactory<GrFragmentProcessor>::Create(d)); SkASSERT(fp); // finally add the stage to the correct pipeline in the drawstate @@ -309,9 +356,42 @@ bool GrDrawTarget::programUnitTest(GrContext* context, int maxStages) { this->drawBatch(pipelineBuilder, batch); } - // Flush everything, test passes if flush is successful(ie, no asserts are hit, no crashes) this->flush(); + + // Validate that GrFPs work correctly without an input. + GrSurfaceDesc rtDesc; + rtDesc.fWidth = kRenderTargetWidth; + rtDesc.fHeight = kRenderTargetHeight; + rtDesc.fFlags = kRenderTarget_GrSurfaceFlag; + rtDesc.fConfig = kRGBA_8888_GrPixelConfig; + SkAutoTUnref<GrRenderTarget> rt( + fContext->textureProvider()->createTexture(rtDesc, false)->asRenderTarget()); + int fpFactoryCnt = GrProcessorTestFactory<GrFragmentProcessor>::Count(); + for (int i = 0; i < fpFactoryCnt; ++i) { + // Since FP factories internally randomize, call each 10 times. + for (int j = 0; j < 10; ++j) { + SkAutoTUnref<GrDrawBatch> batch(GrRandomDrawBatch(&random, context)); + SkASSERT(batch); + GrProcessorDataManager procDataManager; + GrProcessorTestData ptd(&random, context, &procDataManager, this->caps(), + dummyTextures); + GrPipelineBuilder builder; + builder.setXPFactory(GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref(); + builder.setRenderTarget(rt); + builder.setClip(clip); + + SkAutoTUnref<const GrFragmentProcessor> fp( + GrProcessorTestFactory<GrFragmentProcessor>::CreateIdx(i, &ptd)); + SkAutoTUnref<const GrFragmentProcessor> blockFP( + BlockInputFragmentProcessor::Create(fp)); + builder.addColorFragmentProcessor(blockFP); + + this->drawBatch(builder, batch); + this->flush(); + } + } + return true; } |