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 "SkOverdrawColorFilter.h" 9 10 void SkOverdrawColorFilter::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const { 11 for (int x = 0; x < count; x++) { 12 uint8_t alpha = SkGetPackedA32(src[x]); 13 if (alpha >= kNumColors) { 14 alpha = kNumColors - 1; 15 } 16 17 dst[x] = fColors[alpha]; 18 } 19 } 20 21 void SkOverdrawColorFilter::toString(SkString* str) const { 22 str->append("SkOverdrawColorFilter ("); 23 for (int i = 0; i < kNumColors; i++) { 24 str->appendf("%d: %x\n", i, fColors[i]); 25 } 26 str->append(")"); 27 } 28 29 void SkOverdrawColorFilter::flatten(SkWriteBuffer& buffer) const { 30 buffer.writeByteArray(fColors, kNumColors * sizeof(SkPMColor)); 31 } 32 33 sk_sp<SkFlattenable> SkOverdrawColorFilter::CreateProc(SkReadBuffer& buffer) { 34 SkPMColor colors[kNumColors]; 35 size_t size = buffer.getArrayCount(); 36 if (!buffer.validate(size == sizeof(colors))) { 37 return nullptr; 38 } 39 if (!buffer.readByteArray(colors, sizeof(colors))) { 40 return nullptr; 41 } 42 43 return SkOverdrawColorFilter::Make(colors); 44 } 45 46 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkOverdrawColorFilter) 47 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkOverdrawColorFilter) 48 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 49 50 #if SK_SUPPORT_GPU 51 52 #include "GrFragmentProcessor.h" 53 #include "glsl/GrGLSLFragmentProcessor.h" 54 #include "glsl/GrGLSLFragmentShaderBuilder.h" 55 56 class OverdrawFragmentProcessor : public GrFragmentProcessor { 57 public: 58 static sk_sp<GrFragmentProcessor> Make(const SkPMColor* colors); 59 60 const char* name() const override { return "Overdraw"; } 61 private: 62 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; 63 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {} 64 bool onIsEqual(const GrFragmentProcessor&) const override; 65 66 OverdrawFragmentProcessor(const GrColor4f* colors); 67 68 GrColor4f fColors[SkOverdrawColorFilter::kNumColors]; 69 70 typedef GrFragmentProcessor INHERITED; 71 }; 72 73 class GLOverdrawFragmentProcessor : public GrGLSLFragmentProcessor { 74 public: 75 GLOverdrawFragmentProcessor(const GrColor4f* colors); 76 77 void emitCode(EmitArgs&) override; 78 79 protected: 80 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override {} 81 82 private: 83 GrColor4f fColors[SkOverdrawColorFilter::kNumColors]; 84 85 typedef GrGLSLFragmentProcessor INHERITED; 86 }; 87 88 sk_sp<GrFragmentProcessor> SkOverdrawColorFilter::asFragmentProcessor(GrContext*, 89 SkColorSpace*) const { 90 return OverdrawFragmentProcessor::Make(fColors); 91 } 92 93 sk_sp<GrFragmentProcessor> OverdrawFragmentProcessor::Make(const SkPMColor* colors) { 94 GrColor4f grColors[SkOverdrawColorFilter::kNumColors]; 95 for (int i = 0; i < SkOverdrawColorFilter::kNumColors; i++) { 96 grColors[i] = GrColor4f::FromGrColor(GrColorPackRGBA(SkGetPackedR32(colors[i]), 97 SkGetPackedG32(colors[i]), 98 SkGetPackedB32(colors[i]), 99 SkGetPackedA32(colors[i]))); 100 } 101 102 return sk_sp<OverdrawFragmentProcessor>(new OverdrawFragmentProcessor(grColors)); 103 } 104 105 // This could implement the constant input -> constant output optimization, but we don't really 106 // care given how this is used. 107 OverdrawFragmentProcessor::OverdrawFragmentProcessor(const GrColor4f* colors) 108 : INHERITED(kNone_OptimizationFlags) { 109 this->initClassID<OverdrawFragmentProcessor>(); 110 memcpy(fColors, colors, SkOverdrawColorFilter::kNumColors * sizeof(GrColor4f)); 111 } 112 113 GrGLSLFragmentProcessor* OverdrawFragmentProcessor::onCreateGLSLInstance() const { 114 return new GLOverdrawFragmentProcessor(fColors); 115 } 116 117 bool OverdrawFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const { 118 const OverdrawFragmentProcessor& that = other.cast<OverdrawFragmentProcessor>(); 119 return 0 == memcmp(fColors, that.fColors, 120 sizeof(GrColor4f) * SkOverdrawColorFilter::kNumColors); 121 } 122 123 GLOverdrawFragmentProcessor::GLOverdrawFragmentProcessor(const GrColor4f* colors) { 124 memcpy(fColors, colors, SkOverdrawColorFilter::kNumColors * sizeof(GrColor4f)); 125 } 126 127 void GLOverdrawFragmentProcessor::emitCode(EmitArgs& args) { 128 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 129 if (nullptr == args.fInputColor) { 130 fragBuilder->codeAppendf("%s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, 131 fColors[5].fRGBA[0], 132 fColors[5].fRGBA[1], 133 fColors[5].fRGBA[2], 134 fColors[5].fRGBA[3]); 135 } else { 136 fragBuilder->codeAppendf("float alpha = 255.0 * %s.a;", args.fInputColor); 137 fragBuilder->codeAppendf("if (alpha < 0.5) {"); 138 fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, 139 fColors[0].fRGBA[0], 140 fColors[0].fRGBA[1], 141 fColors[0].fRGBA[2], 142 fColors[0].fRGBA[3]); 143 fragBuilder->codeAppendf("} else if (alpha < 1.5) {"); 144 fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, 145 fColors[1].fRGBA[0], 146 fColors[1].fRGBA[1], 147 fColors[1].fRGBA[2], 148 fColors[1].fRGBA[3]); 149 fragBuilder->codeAppendf("} else if (alpha < 2.5) {"); 150 fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, 151 fColors[2].fRGBA[0], 152 fColors[2].fRGBA[1], 153 fColors[2].fRGBA[2], 154 fColors[2].fRGBA[3]); 155 fragBuilder->codeAppendf("} else if (alpha < 3.5) {"); 156 fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, 157 fColors[3].fRGBA[0], 158 fColors[3].fRGBA[1], 159 fColors[3].fRGBA[2], 160 fColors[3].fRGBA[3]); 161 fragBuilder->codeAppendf("} else if (alpha < 4.5) {"); 162 fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, 163 fColors[4].fRGBA[0], 164 fColors[4].fRGBA[1], 165 fColors[4].fRGBA[2], 166 fColors[4].fRGBA[3]); 167 fragBuilder->codeAppendf("} else {"); 168 fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, 169 fColors[5].fRGBA[0], 170 fColors[5].fRGBA[1], 171 fColors[5].fRGBA[2], 172 fColors[5].fRGBA[3]); 173 fragBuilder->codeAppendf("}"); 174 } 175 } 176 177 #endif 178