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