Chromium Code Reviews| Index: src/utils/debugger/SkOverdrawMode.cpp |
| diff --git a/src/utils/debugger/SkOverdrawMode.cpp b/src/utils/debugger/SkOverdrawMode.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..9dd62db363828af0a31f6cddf42df54175b0fa90 |
| --- /dev/null |
| +++ b/src/utils/debugger/SkOverdrawMode.cpp |
| @@ -0,0 +1,331 @@ |
| +/* |
| + * Copyright 2016 Google Inc. |
| + * |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + */ |
| + |
| +#include "SkOverdrawMode.h" |
| +#include "SkXfermode.h" |
| + |
| +#if SK_SUPPORT_GPU |
| +#include "GrFragmentProcessor.h" |
| +#include "GrInvariantOutput.h" |
| +#include "GrXferProcessor.h" |
| +#include "glsl/GrGLSLFragmentProcessor.h" |
| +#include "glsl/GrGLSLFragmentShaderBuilder.h" |
| +#include "glsl/GrGLSLXferProcessor.h" |
| + |
| + /////////////////////////////////////////////////////////////////////////////// |
| + // Fragment Processor |
| + /////////////////////////////////////////////////////////////////////////////// |
| + |
| +class GLOverdrawFP; |
| + |
| +class GrOverdrawFP : public GrFragmentProcessor { |
| +public: |
| + static const GrFragmentProcessor* Create(const GrFragmentProcessor* dst) { |
| + return new GrOverdrawFP(dst); |
| + } |
| + |
| + ~GrOverdrawFP() override { } |
| + |
| + const char* name() const override { return "Overdraw"; } |
| + |
| + SkString dumpInfo() const override { |
| + SkString str; |
| + return str; |
| + } |
| + |
| +private: |
| + GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; |
| + |
| + void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder* b) const override; |
| + |
| + bool onIsEqual(const GrFragmentProcessor&) const override { return true; } |
| + |
| + void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
| + inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); |
| + } |
| + |
| + GrOverdrawFP(const GrFragmentProcessor* dst) { |
| + this->initClassID<GrOverdrawFP>(); |
| + |
| + SkASSERT(dst); |
| + SkDEBUGCODE(int dstIndex = )this->registerChildProcessor(dst); |
| + SkASSERT(0 == dstIndex); |
| + } |
| + |
| + GR_DECLARE_FRAGMENT_PROCESSOR_TEST; |
| + typedef GrFragmentProcessor INHERITED; |
| +}; |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +static void add_overdraw_code(GrGLSLFragmentBuilder* fragBuilder, |
| + const char* dstColor, |
| + const char* outputColor) { |
| + |
| + fragBuilder->codeAppend("vec4 gTable[11] = vec4[11]("); |
| + fragBuilder->codeAppend("vec4(0, 0, 0, 0.0),"); |
| + fragBuilder->codeAppend("vec4(0.5, 0.617, 1.0, 1.0),"); |
| + fragBuilder->codeAppend("vec4(0.664, 0.723, 0.83, 1.0),"); |
| + fragBuilder->codeAppend("vec4(0.832, 0.762, 0.664, 1.0),"); |
| + fragBuilder->codeAppend("vec4(1, 0.75, 0.496, 1.0),"); |
| + fragBuilder->codeAppend("vec4(1, 0.723, 0.332, 1.0),"); |
| + fragBuilder->codeAppend("vec4(1, 0.645, 0.164, 1.0),"); |
| + fragBuilder->codeAppend("vec4(1, 0.527, 0, 1.0),"); |
| + fragBuilder->codeAppend("vec4(1, 0.371, 0, 1.0),"); |
| + fragBuilder->codeAppend("vec4(1, 0.195, 0, 1.0),"); |
| + fragBuilder->codeAppend("vec4(1, 0, 0, 1.0)"); |
| + fragBuilder->codeAppend(");"); |
| + |
| + fragBuilder->codeAppend("int idx;"); |
| + fragBuilder->codeAppendf("vec4 dst = %s;", dstColor); |
| + fragBuilder->codeAppend("if (dst.r < 0.25) { idx = 0; }"); |
| + // cap 'idx' at 9 for upcoming increment |
| + fragBuilder->codeAppend("else if (dst.g < 0.0977) { idx = 9; }"); |
| + fragBuilder->codeAppend("else if (dst.b > 0.08) { idx = 7 - int(6 * dst.b + 0.5); }"); |
| + fragBuilder->codeAppend("else { idx = 10 - int(5.7 * dst.g + 0.5); }"); |
| + fragBuilder->codeAppend("idx++;"); |
| + fragBuilder->codeAppendf("%s = gTable[idx];", outputColor); |
| +} |
| + |
| +class GLOverdrawFP : public GrGLSLFragmentProcessor { |
| +public: |
| + GLOverdrawFP(const GrOverdrawFP&) {} |
| + |
| + ~GLOverdrawFP() override {} |
| + |
| + void emitCode(EmitArgs& args) override { |
| + GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; |
| + SkString dstColor("dstColor"); |
| + this->emitChild(0, nullptr, &dstColor, args); |
| + |
| + add_overdraw_code(fragBuilder, dstColor.c_str(), args.fOutputColor); |
| + } |
| + |
| + static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*) { } |
| + |
| +private: |
| + typedef GrGLSLFragmentProcessor INHERITED; |
| +}; |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +GrGLSLFragmentProcessor* GrOverdrawFP::onCreateGLSLInstance() const { |
| + return new GLOverdrawFP(*this); |
| +} |
| + |
| +void GrOverdrawFP::onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const { |
| + GLOverdrawFP::GenKey(*this, caps, b); |
| +} |
| + |
| +const GrFragmentProcessor* GrOverdrawFP::TestCreate(GrProcessorTestData* d) { |
| + SkAutoTUnref<const GrFragmentProcessor> dst(GrProcessorUnitTest::CreateChildFP(d)); |
| + return new GrOverdrawFP(dst); |
| +} |
| + |
| +GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrOverdrawFP); |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| +// Xfer Processor |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +class OverdrawXP : public GrXferProcessor { |
| +public: |
| + OverdrawXP(const DstTexture* dstTexture, bool hasMixedSamples) |
| + : INHERITED(dstTexture, true, hasMixedSamples) { |
| + this->initClassID<OverdrawXP>(); |
| + } |
| + |
| + const char* name() const override { return "Overdraw"; } |
| + |
| + GrGLSLXferProcessor* createGLSLInstance() const override; |
| + |
| +private: |
| + GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations, |
| + bool doesStencilWrite, |
| + GrColor* overrideColor, |
| + const GrCaps& caps) const override { |
| + return GrXferProcessor::kNone_OptFlags; |
|
egdaniel
2016/01/20 14:28:34
I think this can return ignore color right?
robertphillips
2016/01/20 15:45:10
Done.
|
| + } |
| + |
| + void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override; |
| + |
| + bool onIsEqual(const GrXferProcessor&) const override { return true; } |
| + |
| + typedef GrXferProcessor INHERITED; |
| +}; |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +class GLOverdrawXP : public GrGLSLXferProcessor { |
| +public: |
| + GLOverdrawXP(const OverdrawXP&) { } |
| + |
| + ~GLOverdrawXP() override {} |
| + |
| + static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*) { } |
| + |
| +private: |
| + void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder, |
| + GrGLSLUniformHandler* uniformHandler, |
| + const char* srcColor, |
| + const char* srcCoverage, |
| + const char* dstColor, |
| + const char* outColor, |
| + const char* outColorSecondary, |
| + const GrXferProcessor& proc) override { |
| + add_overdraw_code(fragBuilder, dstColor, outColor); |
| + |
| + // Apply coverage. |
| + if (proc.dstReadUsesMixedSamples()) { |
|
egdaniel
2016/01/20 14:28:34
Instead of copying and pasting this code into almo
robertphillips
2016/01/20 15:45:10
Done.
|
| + if (srcCoverage) { |
| + fragBuilder->codeAppendf("%s *= %s;", outColor, srcCoverage); |
| + fragBuilder->codeAppendf("%s = %s;", outColorSecondary, srcCoverage); |
| + } else { |
| + fragBuilder->codeAppendf("%s = vec4(1.0);", outColorSecondary); |
| + } |
| + } else if (srcCoverage) { |
| + fragBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;", |
| + outColor, srcCoverage, outColor, srcCoverage, dstColor); |
| + } |
| + } |
| + |
| + void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override { }; |
| + |
| + typedef GrGLSLXferProcessor INHERITED; |
| +}; |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +void OverdrawXP::onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const { |
| + GLOverdrawXP::GenKey(*this, caps, b); |
| +} |
| + |
| +GrGLSLXferProcessor* OverdrawXP::createGLSLInstance() const { return new GLOverdrawXP(*this); } |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| +class GrOverdrawXPFactory : public GrXPFactory { |
| +public: |
| + static GrXPFactory* Create() { return new GrOverdrawXPFactory(); } |
| + |
| + void getInvariantBlendedColor(const GrProcOptInfo& colorPOI, |
| + GrXPFactory::InvariantBlendedColor* blendedColor) const override { |
| + blendedColor->fWillBlendWithDst = true; |
| + blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; |
| + } |
| + |
| +private: |
| + GrOverdrawXPFactory() { |
| + this->initClassID<GrOverdrawXPFactory>(); |
| + } |
| + |
| + GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, |
| + const GrPipelineOptimizations& optimizations, |
| + bool hasMixedSamples, |
| + const DstTexture* dstTexture) const override { |
| + return new OverdrawXP(dstTexture, hasMixedSamples); |
| + } |
| + |
| + bool willReadDstColor(const GrCaps& caps, |
| + const GrPipelineOptimizations& optimizations, |
| + bool hasMixedSamples) const override { |
| + return true; |
| + } |
| + |
| + bool onIsEqual(const GrXPFactory& xpfBase) const override { return true; } |
| + |
| + GR_DECLARE_XP_FACTORY_TEST; |
| + |
| + typedef GrXPFactory INHERITED; |
| +}; |
| + |
| +GR_DEFINE_XP_FACTORY_TEST(GrOverdrawXPFactory); |
| + |
| +const GrXPFactory* GrOverdrawXPFactory::TestCreate(GrProcessorTestData* d) { |
| + return GrOverdrawXPFactory::Create(); |
| +} |
| +#endif |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| +class SkOverdrawXfermode : public SkXfermode { |
| +public: |
| + static SkXfermode* Create() { |
| + return new SkOverdrawXfermode; |
| + } |
| + |
| + SkPMColor xferColor(SkPMColor src, SkPMColor dst) const override { |
| + // This table encodes the color progression of the overdraw visualization |
| + static const SkPMColor gTable[] = { |
| + SkPackARGB32(0x00, 0x00, 0x00, 0x00), |
| + SkPackARGB32(0xFF, 128, 158, 255), |
| + SkPackARGB32(0xFF, 170, 185, 212), |
| + SkPackARGB32(0xFF, 213, 195, 170), |
| + SkPackARGB32(0xFF, 255, 192, 127), |
| + SkPackARGB32(0xFF, 255, 185, 85), |
| + SkPackARGB32(0xFF, 255, 165, 42), |
| + SkPackARGB32(0xFF, 255, 135, 0), |
| + SkPackARGB32(0xFF, 255, 95, 0), |
| + SkPackARGB32(0xFF, 255, 50, 0), |
| + SkPackARGB32(0xFF, 255, 0, 0) |
| + }; |
| + |
| + |
| + int idx; |
| + if (SkColorGetR(dst) < 64) { // 0 |
| + idx = 0; |
| + } else if (SkColorGetG(dst) < 25) { // 10 |
| + idx = 9; // cap at 9 for upcoming increment |
| + } else if ((SkColorGetB(dst)+21)/42 > 0) { // 1-6 |
| + idx = 7 - (SkColorGetB(dst)+21)/42; |
| + } else { // 7-9 |
| + idx = 10 - (SkColorGetG(dst)+22)/45; |
| + } |
| + ++idx; |
|
egdaniel
2016/01/20 14:28:34
Why is this +1 here? Why not either get right of t
robertphillips
2016/01/20 15:45:10
Done. Here and in the gpu implementation.
|
| + SkASSERT(idx < (int)SK_ARRAY_COUNT(gTable)); |
| + |
| + return gTable[idx]; |
| + } |
| + |
| + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkOverdrawXfermode) |
| + |
| +#if SK_SUPPORT_GPU |
| + bool asFragmentProcessor(const GrFragmentProcessor** output, |
| + const GrFragmentProcessor* dst) const override { |
| + if (output) { |
| + *output = GrOverdrawFP::Create(dst); |
| + } |
| + return true; |
| + } |
| + |
| + bool asXPFactory(GrXPFactory** xpf) const override { |
| + if (xpf) { |
| + *xpf = GrOverdrawXPFactory::Create(); |
| + } |
| + return true; |
| + } |
| +#endif |
| + |
| +#ifndef SK_IGNORE_TO_STRING |
| + void toString(SkString* str) const override { str->set("SkOverdrawXfermode"); } |
| +#endif |
| + |
| +private: |
| + friend class SkOverdrawMode; |
| + |
| + void flatten(SkWriteBuffer& buffer) const override { } |
| + |
| + typedef SkXfermode INHERITED; |
| +}; |
| + |
| +SkFlattenable* SkOverdrawXfermode::CreateProc(SkReadBuffer& buffer) { |
| + return Create(); |
| +} |
| + |
| +SkXfermode* SkOverdrawMode::Create() { return new SkOverdrawXfermode; } |
| + |
| +SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkOverdrawMode) |
| + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkOverdrawXfermode) |
| +SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |