Matt Sarett | 030cbd5 | 2016-11-22 15:48:50 -0500 | [diff] [blame] | 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 "GrInvariantOutput.h" |
| 54 | #include "glsl/GrGLSLFragmentProcessor.h" |
| 55 | #include "glsl/GrGLSLFragmentShaderBuilder.h" |
| 56 | |
| 57 | class OverdrawFragmentProcessor : public GrFragmentProcessor { |
| 58 | public: |
| 59 | static sk_sp<GrFragmentProcessor> Make(const SkPMColor* colors); |
| 60 | |
| 61 | const char* name() const override { return "Overdraw"; } |
| 62 | |
| 63 | private: |
| 64 | GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; |
Brian Salomon | 94efbf5 | 2016-11-29 13:43:05 -0500 | [diff] [blame^] | 65 | void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {} |
Matt Sarett | 030cbd5 | 2016-11-22 15:48:50 -0500 | [diff] [blame] | 66 | bool onIsEqual(const GrFragmentProcessor&) const override; |
| 67 | void onComputeInvariantOutput(GrInvariantOutput* inout) const override; |
| 68 | |
| 69 | OverdrawFragmentProcessor(const GrColor4f* colors); |
| 70 | |
| 71 | GrColor4f fColors[SkOverdrawColorFilter::kNumColors]; |
| 72 | |
| 73 | typedef GrFragmentProcessor INHERITED; |
| 74 | }; |
| 75 | |
| 76 | class GLOverdrawFragmentProcessor : public GrGLSLFragmentProcessor { |
| 77 | public: |
| 78 | GLOverdrawFragmentProcessor(const GrColor4f* colors); |
| 79 | |
| 80 | void emitCode(EmitArgs&) override; |
| 81 | |
| 82 | protected: |
| 83 | void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override {} |
| 84 | |
| 85 | private: |
| 86 | GrColor4f fColors[SkOverdrawColorFilter::kNumColors]; |
| 87 | |
| 88 | typedef GrGLSLFragmentProcessor INHERITED; |
| 89 | }; |
| 90 | |
| 91 | sk_sp<GrFragmentProcessor> SkOverdrawColorFilter::asFragmentProcessor(GrContext*, |
| 92 | SkColorSpace*) const { |
| 93 | return OverdrawFragmentProcessor::Make(fColors); |
| 94 | } |
| 95 | |
| 96 | sk_sp<GrFragmentProcessor> OverdrawFragmentProcessor::Make(const SkPMColor* colors) { |
| 97 | GrColor4f grColors[SkOverdrawColorFilter::kNumColors]; |
| 98 | for (int i = 0; i < SkOverdrawColorFilter::kNumColors; i++) { |
| 99 | grColors[i] = GrColor4f::FromGrColor(GrColorPackRGBA(SkGetPackedR32(colors[i]), |
| 100 | SkGetPackedG32(colors[i]), |
| 101 | SkGetPackedB32(colors[i]), |
| 102 | SkGetPackedA32(colors[i]))); |
| 103 | } |
| 104 | |
| 105 | return sk_sp<OverdrawFragmentProcessor>(new OverdrawFragmentProcessor(grColors)); |
| 106 | } |
| 107 | |
| 108 | OverdrawFragmentProcessor::OverdrawFragmentProcessor(const GrColor4f* colors) { |
| 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 | void OverdrawFragmentProcessor::onComputeInvariantOutput(GrInvariantOutput* inout) const { |
| 124 | inout->invalidateComponents(kRGBA_GrColorComponentFlags, GrInvariantOutput::kWill_ReadInput); |
| 125 | } |
| 126 | |
| 127 | GLOverdrawFragmentProcessor::GLOverdrawFragmentProcessor(const GrColor4f* colors) { |
| 128 | memcpy(fColors, colors, SkOverdrawColorFilter::kNumColors * sizeof(GrColor4f)); |
| 129 | } |
| 130 | |
| 131 | void GLOverdrawFragmentProcessor::emitCode(EmitArgs& args) { |
| 132 | GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; |
| 133 | if (nullptr == args.fInputColor) { |
| 134 | fragBuilder->codeAppendf("%s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, |
| 135 | fColors[5].fRGBA[0], |
| 136 | fColors[5].fRGBA[1], |
| 137 | fColors[5].fRGBA[2], |
| 138 | fColors[5].fRGBA[3]); |
| 139 | } else { |
| 140 | fragBuilder->codeAppendf("float alpha = 255.0 * %s.a;", args.fInputColor); |
| 141 | fragBuilder->codeAppendf("if (alpha < 0.5) {"); |
| 142 | fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, |
| 143 | fColors[0].fRGBA[0], |
| 144 | fColors[0].fRGBA[1], |
| 145 | fColors[0].fRGBA[2], |
| 146 | fColors[0].fRGBA[3]); |
| 147 | fragBuilder->codeAppendf("} else if (alpha < 1.5) {"); |
| 148 | fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, |
| 149 | fColors[1].fRGBA[0], |
| 150 | fColors[1].fRGBA[1], |
| 151 | fColors[1].fRGBA[2], |
| 152 | fColors[1].fRGBA[3]); |
| 153 | fragBuilder->codeAppendf("} else if (alpha < 2.5) {"); |
| 154 | fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, |
| 155 | fColors[2].fRGBA[0], |
| 156 | fColors[2].fRGBA[1], |
| 157 | fColors[2].fRGBA[2], |
| 158 | fColors[2].fRGBA[3]); |
| 159 | fragBuilder->codeAppendf("} else if (alpha < 3.5) {"); |
| 160 | fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, |
| 161 | fColors[3].fRGBA[0], |
| 162 | fColors[3].fRGBA[1], |
| 163 | fColors[3].fRGBA[2], |
| 164 | fColors[3].fRGBA[3]); |
| 165 | fragBuilder->codeAppendf("} else if (alpha < 4.5) {"); |
| 166 | fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, |
| 167 | fColors[4].fRGBA[0], |
| 168 | fColors[4].fRGBA[1], |
| 169 | fColors[4].fRGBA[2], |
| 170 | fColors[4].fRGBA[3]); |
| 171 | fragBuilder->codeAppendf("} else {"); |
| 172 | fragBuilder->codeAppendf(" %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor, |
| 173 | fColors[5].fRGBA[0], |
| 174 | fColors[5].fRGBA[1], |
| 175 | fColors[5].fRGBA[2], |
| 176 | fColors[5].fRGBA[3]); |
| 177 | fragBuilder->codeAppendf("}"); |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | #endif |