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