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 #include "SkColorPriv.h" 9 #include "SkOverdrawMode.h" 10 #include "SkString.h" 11 #include "SkXfermode.h" 12 13 #if SK_SUPPORT_GPU 14 #include "GrFragmentProcessor.h" 15 #include "GrInvariantOutput.h" 16 #include "GrXferProcessor.h" 17 #include "glsl/GrGLSLFragmentProcessor.h" 18 #include "glsl/GrGLSLFragmentShaderBuilder.h" 19 #include "glsl/GrGLSLXferProcessor.h" 20 21 /////////////////////////////////////////////////////////////////////////////// 22 // Fragment Processor 23 /////////////////////////////////////////////////////////////////////////////// 24 25 class GLOverdrawFP; 26 27 class GrOverdrawFP : public GrFragmentProcessor { 28 public: 29 static const GrFragmentProcessor* Create(const GrFragmentProcessor* dst) { 30 return new GrOverdrawFP(dst); 31 } 32 33 ~GrOverdrawFP() override { } 34 35 const char* name() const override { return "Overdraw"; } 36 37 SkString dumpInfo() const override { 38 SkString str; 39 return str; 40 } 41 42 private: 43 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; 44 45 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder* b) const override; 46 47 bool onIsEqual(const GrFragmentProcessor&) const override { return true; } 48 49 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { 50 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); 51 } 52 53 GrOverdrawFP(const GrFragmentProcessor* dst) { 54 this->initClassID<GrOverdrawFP>(); 55 56 SkASSERT(dst); 57 SkDEBUGCODE(int dstIndex = )this->registerChildProcessor(dst); 58 SkASSERT(0 == dstIndex); 59 } 60 61 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 62 typedef GrFragmentProcessor INHERITED; 63 }; 64 65 /////////////////////////////////////////////////////////////////////////////// 66 67 static void add_overdraw_code(GrGLSLFragmentBuilder* fragBuilder, 68 const char* dstColor, 69 const char* outputColor) { 70 71 static const GrGLSLShaderVar gColorTableArgs[] = { 72 // TODO: once kInt_GrSLType lands - switch this over 73 GrGLSLShaderVar("index", kFloat_GrSLType), 74 }; 75 SkString colorTableFuncName; 76 77 // The 'colorTable' function exists to work around older GLSL's prohibition 78 // of initialized arrays. It takes an integer index and just returns the 79 // corresponding color. 80 fragBuilder->emitFunction(kVec4f_GrSLType, 81 "colorTable", 82 SK_ARRAY_COUNT(gColorTableArgs), 83 gColorTableArgs, 84 "if (index < 1.5) { return vec4(0.5, 0.617, 1.0, 1.0); }" 85 "if (index < 2.5) { return vec4(0.664, 0.723, 0.83, 1.0); }" 86 "if (index < 3.5) { return vec4(0.832, 0.762, 0.664, 1.0); }" 87 "if (index < 4.5) { return vec4(1, 0.75, 0.496, 1.0); }" 88 "if (index < 5.5) { return vec4(1, 0.723, 0.332, 1.0); }" 89 "if (index < 6.5) { return vec4(1, 0.645, 0.164, 1.0); }" 90 "if (index < 7.5) { return vec4(1, 0.527, 0, 1.0); }" 91 "if (index < 8.5) { return vec4(1, 0.371, 0, 1.0); }" 92 "if (index < 9.5) { return vec4(1, 0.195, 0, 1.0); }" 93 "return vec4(1, 0, 0, 1.0);", 94 &colorTableFuncName); 95 96 fragBuilder->codeAppend("int nextIdx;"); 97 fragBuilder->codeAppendf("vec4 dst = %s;", dstColor); 98 fragBuilder->codeAppend("if (dst.r < 0.25) { nextIdx = 1; }"); 99 // cap 'idx' at 10 100 fragBuilder->codeAppend("else if (dst.g < 0.0977) { nextIdx = 10; }"); 101 fragBuilder->codeAppend("else if (dst.b > 0.08) { nextIdx = 8 - int(6.0 * dst.b + 0.5); }"); 102 fragBuilder->codeAppend("else { nextIdx = 11 - int(5.7 * dst.g + 0.5); }"); 103 fragBuilder->codeAppendf("%s = %s(float(nextIdx));", outputColor, colorTableFuncName.c_str()); 104 } 105 106 class GLOverdrawFP : public GrGLSLFragmentProcessor { 107 public: 108 void emitCode(EmitArgs& args) override { 109 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; 110 SkString dstColor("dstColor"); 111 this->emitChild(0, nullptr, &dstColor, args); 112 113 add_overdraw_code(fragBuilder, dstColor.c_str(), args.fOutputColor); 114 } 115 116 static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*) { } 117 118 private: 119 typedef GrGLSLFragmentProcessor INHERITED; 120 }; 121 122 /////////////////////////////////////////////////////////////////////////////// 123 124 GrGLSLFragmentProcessor* GrOverdrawFP::onCreateGLSLInstance() const { 125 return new GLOverdrawFP; 126 } 127 128 void GrOverdrawFP::onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const { 129 GLOverdrawFP::GenKey(*this, caps, b); 130 } 131 132 const GrFragmentProcessor* GrOverdrawFP::TestCreate(GrProcessorTestData* d) { 133 SkAutoTUnref<const GrFragmentProcessor> dst(GrProcessorUnitTest::CreateChildFP(d)); 134 return new GrOverdrawFP(dst); 135 } 136 137 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrOverdrawFP); 138 139 /////////////////////////////////////////////////////////////////////////////// 140 // Xfer Processor 141 /////////////////////////////////////////////////////////////////////////////// 142 143 class OverdrawXP : public GrXferProcessor { 144 public: 145 OverdrawXP(const DstTexture* dstTexture, bool hasMixedSamples) 146 : INHERITED(dstTexture, true, hasMixedSamples) { 147 this->initClassID<OverdrawXP>(); 148 } 149 150 const char* name() const override { return "Overdraw"; } 151 152 GrGLSLXferProcessor* createGLSLInstance() const override; 153 154 private: 155 GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations, 156 bool doesStencilWrite, 157 GrColor* overrideColor, 158 const GrCaps& caps) const override { 159 // We never look at the color input 160 return GrXferProcessor::kIgnoreColor_OptFlag; 161 } 162 163 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override; 164 165 bool onIsEqual(const GrXferProcessor&) const override { return true; } 166 167 typedef GrXferProcessor INHERITED; 168 }; 169 170 /////////////////////////////////////////////////////////////////////////////// 171 172 class GLOverdrawXP : public GrGLSLXferProcessor { 173 public: 174 GLOverdrawXP(const OverdrawXP&) { } 175 176 ~GLOverdrawXP() override {} 177 178 static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*) { } 179 180 private: 181 void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder, 182 GrGLSLUniformHandler* uniformHandler, 183 const char* srcColor, 184 const char* srcCoverage, 185 const char* dstColor, 186 const char* outColor, 187 const char* outColorSecondary, 188 const GrXferProcessor& proc) override { 189 add_overdraw_code(fragBuilder, dstColor, outColor); 190 191 // Apply coverage. 192 INHERITED::DefaultCoverageModulation(fragBuilder, srcCoverage, dstColor, outColor, 193 outColorSecondary, proc); 194 } 195 196 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override { }; 197 198 typedef GrGLSLXferProcessor INHERITED; 199 }; 200 201 /////////////////////////////////////////////////////////////////////////////// 202 203 void OverdrawXP::onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const { 204 GLOverdrawXP::GenKey(*this, caps, b); 205 } 206 207 GrGLSLXferProcessor* OverdrawXP::createGLSLInstance() const { return new GLOverdrawXP(*this); } 208 209 /////////////////////////////////////////////////////////////////////////////// 210 class GrOverdrawXPFactory : public GrXPFactory { 211 public: 212 static GrXPFactory* Create() { return new GrOverdrawXPFactory(); } 213 214 void getInvariantBlendedColor(const GrProcOptInfo& colorPOI, 215 GrXPFactory::InvariantBlendedColor* blendedColor) const override { 216 blendedColor->fWillBlendWithDst = true; 217 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; 218 } 219 220 private: 221 GrOverdrawXPFactory() { 222 this->initClassID<GrOverdrawXPFactory>(); 223 } 224 225 GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, 226 const GrPipelineOptimizations& optimizations, 227 bool hasMixedSamples, 228 const DstTexture* dstTexture) const override { 229 return new OverdrawXP(dstTexture, hasMixedSamples); 230 } 231 232 bool onWillReadDstColor(const GrCaps& caps, 233 const GrPipelineOptimizations& optimizations, 234 bool hasMixedSamples) const override { 235 return true; 236 } 237 238 bool onIsEqual(const GrXPFactory& xpfBase) const override { return true; } 239 240 GR_DECLARE_XP_FACTORY_TEST; 241 242 typedef GrXPFactory INHERITED; 243 }; 244 245 GR_DEFINE_XP_FACTORY_TEST(GrOverdrawXPFactory); 246 247 const GrXPFactory* GrOverdrawXPFactory::TestCreate(GrProcessorTestData* d) { 248 return GrOverdrawXPFactory::Create(); 249 } 250 #endif 251 252 /////////////////////////////////////////////////////////////////////////////// 253 class SkOverdrawXfermode : public SkXfermode { 254 public: 255 static SkXfermode* Create() { 256 return new SkOverdrawXfermode; 257 } 258 259 SkPMColor xferColor(SkPMColor src, SkPMColor dst) const override { 260 // This table encodes the color progression of the overdraw visualization 261 static const SkPMColor gTable[] = { 262 SkPackARGB32(0x00, 0x00, 0x00, 0x00), 263 SkPackARGB32(0xFF, 128, 158, 255), 264 SkPackARGB32(0xFF, 170, 185, 212), 265 SkPackARGB32(0xFF, 213, 195, 170), 266 SkPackARGB32(0xFF, 255, 192, 127), 267 SkPackARGB32(0xFF, 255, 185, 85), 268 SkPackARGB32(0xFF, 255, 165, 42), 269 SkPackARGB32(0xFF, 255, 135, 0), 270 SkPackARGB32(0xFF, 255, 95, 0), 271 SkPackARGB32(0xFF, 255, 50, 0), 272 SkPackARGB32(0xFF, 255, 0, 0) 273 }; 274 275 276 int nextIdx; 277 if (SkColorGetR(dst) < 64) { // dst color is the 0th color so the next color is 1 278 nextIdx = 1; 279 } else if (SkColorGetG(dst) < 25) { // dst color is the 10th color so cap there 280 nextIdx = 10; 281 } else if ((SkColorGetB(dst)+21)/42 > 0) { // dst color is one of 1-6 282 nextIdx = 8 - (SkColorGetB(dst)+21)/42; 283 } else { // dst color is between 7 and 9 284 nextIdx = 11 - (SkColorGetG(dst)+22)/45; 285 } 286 SkASSERT(nextIdx < (int)SK_ARRAY_COUNT(gTable)); 287 288 return gTable[nextIdx]; 289 } 290 291 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkOverdrawXfermode) 292 293 #if SK_SUPPORT_GPU 294 const GrFragmentProcessor* getFragmentProcessorForImageFilter( 295 const GrFragmentProcessor* dst) const override { 296 return GrOverdrawFP::Create(dst); 297 } 298 299 GrXPFactory* asXPFactory() const override { 300 return GrOverdrawXPFactory::Create(); 301 } 302 #endif 303 304 #ifndef SK_IGNORE_TO_STRING 305 void toString(SkString* str) const override { str->set("SkOverdrawXfermode"); } 306 #endif 307 308 private: 309 friend class SkOverdrawMode; 310 311 void flatten(SkWriteBuffer& buffer) const override { } 312 313 typedef SkXfermode INHERITED; 314 }; 315 316 SkFlattenable* SkOverdrawXfermode::CreateProc(SkReadBuffer& buffer) { 317 return Create(); 318 } 319 320 SkXfermode* SkOverdrawMode::Create() { return new SkOverdrawXfermode; } 321 322 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkOverdrawMode) 323 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkOverdrawXfermode) 324 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 325