SkLumaColorFilter.cpp revision 8b0e8ac5f582de80356019406e2975079bf0829d
1/*
2 * Copyright 2013 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 "SkLumaColorFilter.h"
9
10#include "SkColorPriv.h"
11#include "SkString.h"
12
13#if SK_SUPPORT_GPU
14#include "gl/GrGLEffect.h"
15#include "GrContext.h"
16#include "GrTBackendEffectFactory.h"
17#endif
18
19void SkLumaColorFilter::filterSpan(const SkPMColor src[], int count,
20                                   SkPMColor dst[]) const {
21    for (int i = 0; i < count; ++i) {
22        SkPMColor c = src[i];
23
24        /*
25         * While LuminanceToAlpha is defined to operate on un-premultiplied
26         * inputs, due to the final alpha scaling it can be computed based on
27         * premultipled components:
28         *
29         *   LumA = (k1 * r / a + k2 * g / a + k3 * b / a) * a
30         *   LumA = (k1 * r + k2 * g + k3 * b)
31         */
32        unsigned luma = SkComputeLuminance(SkGetPackedR32(c),
33                                           SkGetPackedG32(c),
34                                           SkGetPackedB32(c));
35        dst[i] = SkPackARGB32(luma, 0, 0, 0);
36    }
37}
38
39SkColorFilter* SkLumaColorFilter::Create() {
40    return SkNEW(SkLumaColorFilter);
41}
42
43SkLumaColorFilter::SkLumaColorFilter()
44    : INHERITED() {
45}
46
47SkLumaColorFilter::SkLumaColorFilter(SkReadBuffer& buffer)
48    : INHERITED(buffer) {
49}
50
51void SkLumaColorFilter::flatten(SkWriteBuffer&) const {
52}
53
54#ifdef SK_DEVELOPER
55void SkLumaColorFilter::toString(SkString* str) const {
56    str->append("SkLumaColorFilter ");
57}
58#endif
59
60#if SK_SUPPORT_GPU
61class LumaColorFilterEffect : public GrEffect {
62public:
63    static GrEffectRef* Create() {
64        AutoEffectUnref effect(SkNEW(LumaColorFilterEffect));
65        return CreateEffectRef(effect);
66    }
67
68    static const char* Name() { return "Luminance-to-Alpha"; }
69
70    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
71        return GrTBackendEffectFactory<LumaColorFilterEffect>::getInstance();
72    }
73
74    virtual void getConstantColorComponents(GrColor* color,
75                                            uint32_t* validFlags) const SK_OVERRIDE {
76        // The output is always black.
77        *color = GrColorPackRGBA(0, 0, 0, GrColorUnpackA(*color));
78        *validFlags = kRGB_GrColorComponentFlags;
79    }
80
81    class GLEffect : public GrGLEffect {
82    public:
83        GLEffect(const GrBackendEffectFactory& factory,
84                 const GrDrawEffect&)
85        : INHERITED(factory) {
86        }
87
88        static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&) {
89            // this class always generates the same code.
90            return 0;
91        }
92
93        virtual void emitCode(GrGLShaderBuilder* builder,
94                              const GrDrawEffect&,
95                              EffectKey,
96                              const char* outputColor,
97                              const char* inputColor,
98                              const TransformedCoordsArray&,
99                              const TextureSamplerArray&) SK_OVERRIDE {
100            if (NULL == inputColor) {
101                inputColor = "vec4(1)";
102            }
103
104            builder->fsCodeAppendf("\tfloat luma = dot(vec3(%f, %f, %f), %s.rgb);\n",
105                                   SK_ITU_BT709_LUM_COEFF_R,
106                                   SK_ITU_BT709_LUM_COEFF_G,
107                                   SK_ITU_BT709_LUM_COEFF_B,
108                                   inputColor);
109            builder->fsCodeAppendf("\t%s = vec4(0, 0, 0, luma);\n",
110                                   outputColor);
111
112        }
113
114    private:
115        typedef GrGLEffect INHERITED;
116    };
117
118private:
119    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE {
120        return true;
121    }
122};
123
124GrEffectRef* SkLumaColorFilter::asNewEffect(GrContext*) const {
125    return LumaColorFilterEffect::Create();
126}
127#endif
128