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/GrGLProcessor.h"
15#include "gl/builders/GrGLProgramBuilder.h"
16#include "GrContext.h"
17#include "GrTBackendProcessorFactory.h"
18#endif
19
20void SkLumaColorFilter::filterSpan(const SkPMColor src[], int count,
21                                   SkPMColor dst[]) const {
22    for (int i = 0; i < count; ++i) {
23        SkPMColor c = src[i];
24
25        /*
26         * While LuminanceToAlpha is defined to operate on un-premultiplied
27         * inputs, due to the final alpha scaling it can be computed based on
28         * premultipled components:
29         *
30         *   LumA = (k1 * r / a + k2 * g / a + k3 * b / a) * a
31         *   LumA = (k1 * r + k2 * g + k3 * b)
32         */
33        unsigned luma = SkComputeLuminance(SkGetPackedR32(c),
34                                           SkGetPackedG32(c),
35                                           SkGetPackedB32(c));
36        dst[i] = SkPackARGB32(luma, 0, 0, 0);
37    }
38}
39
40SkColorFilter* SkLumaColorFilter::Create() {
41    return SkNEW(SkLumaColorFilter);
42}
43
44SkLumaColorFilter::SkLumaColorFilter() : INHERITED() {}
45
46#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
47SkLumaColorFilter::SkLumaColorFilter(SkReadBuffer& buffer) : INHERITED(buffer) {}
48#endif
49
50SkFlattenable* SkLumaColorFilter::CreateProc(SkReadBuffer&) {
51    return SkNEW(SkLumaColorFilter);
52}
53
54void SkLumaColorFilter::flatten(SkWriteBuffer&) const {}
55
56#ifndef SK_IGNORE_TO_STRING
57void SkLumaColorFilter::toString(SkString* str) const {
58    str->append("SkLumaColorFilter ");
59}
60#endif
61
62#if SK_SUPPORT_GPU
63class LumaColorFilterEffect : public GrFragmentProcessor {
64public:
65    static GrFragmentProcessor* Create() {
66        GR_CREATE_STATIC_FRAGMENT_PROCESSOR(gLumaEffect, LumaColorFilterEffect, ());
67        return SkRef(gLumaEffect);
68    }
69
70    static const char* Name() { return "Luminance-to-Alpha"; }
71
72    virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE {
73        return GrTBackendFragmentProcessorFactory<LumaColorFilterEffect>::getInstance();
74    }
75
76    virtual void getConstantColorComponents(GrColor* color,
77                                            uint32_t* validFlags) const SK_OVERRIDE {
78        // The output is always black.
79        *color = GrColorPackRGBA(0, 0, 0, GrColorUnpackA(*color));
80        *validFlags = kRGB_GrColorComponentFlags;
81    }
82
83    class GLProcessor : public GrGLFragmentProcessor {
84    public:
85        GLProcessor(const GrBackendProcessorFactory& factory,
86                    const GrProcessor&)
87        : INHERITED(factory) {
88        }
89
90        static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder* b) {}
91
92        virtual void emitCode(GrGLProgramBuilder* builder,
93                              const GrFragmentProcessor&,
94                              const GrProcessorKey&,
95                              const char* outputColor,
96                              const char* inputColor,
97                              const TransformedCoordsArray&,
98                              const TextureSamplerArray&) SK_OVERRIDE {
99            if (NULL == inputColor) {
100                inputColor = "vec4(1)";
101            }
102
103            GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
104            fsBuilder->codeAppendf("\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            fsBuilder->codeAppendf("\t%s = vec4(0, 0, 0, luma);\n",
110                                   outputColor);
111
112        }
113
114    private:
115        typedef GrGLFragmentProcessor INHERITED;
116    };
117
118private:
119    virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE {
120        return true;
121    }
122};
123
124GrFragmentProcessor* SkLumaColorFilter::asFragmentProcessor(GrContext*) const {
125    return LumaColorFilterEffect::Create();
126}
127#endif
128