SkOverdrawColorFilter.cpp revision cb30bb2cb727e276792812c6390547dba474c831
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
10void 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
21void 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
29void SkOverdrawColorFilter::flatten(SkWriteBuffer& buffer) const {
30    buffer.writeByteArray(fColors, kNumColors * sizeof(SkPMColor));
31}
32
33sk_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
46SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkOverdrawColorFilter)
47    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkOverdrawColorFilter)
48SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
49
50#if SK_SUPPORT_GPU
51
52#include "GrFragmentProcessor.h"
53#include "glsl/GrGLSLFragmentProcessor.h"
54#include "glsl/GrGLSLFragmentShaderBuilder.h"
55
56class OverdrawFragmentProcessor : public GrFragmentProcessor {
57public:
58    static sk_sp<GrFragmentProcessor> Make(const SkPMColor* colors);
59
60    const char* name() const override { return "Overdraw"; }
61private:
62    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
63    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
64    bool onIsEqual(const GrFragmentProcessor&) const override;
65
66    OverdrawFragmentProcessor(const GrColor4f* colors);
67
68    GrColor4f fColors[SkOverdrawColorFilter::kNumColors];
69
70    typedef GrFragmentProcessor INHERITED;
71};
72
73class GLOverdrawFragmentProcessor : public GrGLSLFragmentProcessor {
74public:
75    GLOverdrawFragmentProcessor(const GrColor4f* colors);
76
77    void emitCode(EmitArgs&) override;
78
79protected:
80    void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override {}
81
82private:
83    GrColor4f fColors[SkOverdrawColorFilter::kNumColors];
84
85    typedef GrGLSLFragmentProcessor INHERITED;
86};
87
88sk_sp<GrFragmentProcessor> SkOverdrawColorFilter::asFragmentProcessor(GrContext*,
89                                                                      SkColorSpace*) const {
90    return OverdrawFragmentProcessor::Make(fColors);
91}
92
93sk_sp<GrFragmentProcessor> OverdrawFragmentProcessor::Make(const SkPMColor* colors) {
94    GrColor4f grColors[SkOverdrawColorFilter::kNumColors];
95    for (int i = 0; i < SkOverdrawColorFilter::kNumColors; i++) {
96        grColors[i] = GrColor4f::FromGrColor(GrColorPackRGBA(SkGetPackedR32(colors[i]),
97                                                             SkGetPackedG32(colors[i]),
98                                                             SkGetPackedB32(colors[i]),
99                                                             SkGetPackedA32(colors[i])));
100    }
101
102    return sk_sp<OverdrawFragmentProcessor>(new OverdrawFragmentProcessor(grColors));
103}
104
105// This could implement the constant input -> constant output optimization, but we don't really
106// care given how this is used.
107OverdrawFragmentProcessor::OverdrawFragmentProcessor(const GrColor4f* colors)
108        : INHERITED(kNone_OptimizationFlags) {
109    this->initClassID<OverdrawFragmentProcessor>();
110    memcpy(fColors, colors, SkOverdrawColorFilter::kNumColors * sizeof(GrColor4f));
111}
112
113GrGLSLFragmentProcessor* OverdrawFragmentProcessor::onCreateGLSLInstance() const {
114    return new GLOverdrawFragmentProcessor(fColors);
115}
116
117bool 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
123GLOverdrawFragmentProcessor::GLOverdrawFragmentProcessor(const GrColor4f* colors) {
124    memcpy(fColors, colors, SkOverdrawColorFilter::kNumColors * sizeof(GrColor4f));
125}
126
127void GLOverdrawFragmentProcessor::emitCode(EmitArgs& args) {
128    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
129    if (nullptr == args.fInputColor) {
130        fragBuilder->codeAppendf("%s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor,
131                                                                    fColors[5].fRGBA[0],
132                                                                    fColors[5].fRGBA[1],
133                                                                    fColors[5].fRGBA[2],
134                                                                    fColors[5].fRGBA[3]);
135    } else {
136        fragBuilder->codeAppendf("float alpha = 255.0 * %s.a;", args.fInputColor);
137        fragBuilder->codeAppendf("if (alpha < 0.5) {");
138        fragBuilder->codeAppendf("    %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor,
139                                                                        fColors[0].fRGBA[0],
140                                                                        fColors[0].fRGBA[1],
141                                                                        fColors[0].fRGBA[2],
142                                                                        fColors[0].fRGBA[3]);
143        fragBuilder->codeAppendf("} else if (alpha < 1.5) {");
144        fragBuilder->codeAppendf("    %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor,
145                                                                        fColors[1].fRGBA[0],
146                                                                        fColors[1].fRGBA[1],
147                                                                        fColors[1].fRGBA[2],
148                                                                        fColors[1].fRGBA[3]);
149        fragBuilder->codeAppendf("} else if (alpha < 2.5) {");
150        fragBuilder->codeAppendf("    %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor,
151                                                                        fColors[2].fRGBA[0],
152                                                                        fColors[2].fRGBA[1],
153                                                                        fColors[2].fRGBA[2],
154                                                                        fColors[2].fRGBA[3]);
155        fragBuilder->codeAppendf("} else if (alpha < 3.5) {");
156        fragBuilder->codeAppendf("    %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor,
157                                                                        fColors[3].fRGBA[0],
158                                                                        fColors[3].fRGBA[1],
159                                                                        fColors[3].fRGBA[2],
160                                                                        fColors[3].fRGBA[3]);
161        fragBuilder->codeAppendf("} else if (alpha < 4.5) {");
162        fragBuilder->codeAppendf("    %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor,
163                                                                        fColors[4].fRGBA[0],
164                                                                        fColors[4].fRGBA[1],
165                                                                        fColors[4].fRGBA[2],
166                                                                        fColors[4].fRGBA[3]);
167        fragBuilder->codeAppendf("} else {");
168        fragBuilder->codeAppendf("    %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor,
169                                                                        fColors[5].fRGBA[0],
170                                                                        fColors[5].fRGBA[1],
171                                                                        fColors[5].fRGBA[2],
172                                                                        fColors[5].fRGBA[3]);
173        fragBuilder->codeAppendf("}");
174    }
175}
176
177#endif
178