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