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