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