a131b0f4345513a3671801f82d4491aecfaabe34
[platform/upstream/libSkiaSharp.git] / src / effects / SkLumaColorFilter.cpp
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 "GrContext.h"
15 #include "GrInvariantOutput.h"
16 #include "glsl/GrGLSLFragmentProcessor.h"
17 #include "glsl/GrGLSLFragmentShaderBuilder.h"
18 #include "glsl/GrGLSLProgramBuilder.h"
19 #endif
20
21 void SkLumaColorFilter::filterSpan(const SkPMColor src[], int count,
22                                    SkPMColor dst[]) const {
23     for (int i = 0; i < count; ++i) {
24         SkPMColor c = src[i];
25
26         /*
27          * While LuminanceToAlpha is defined to operate on un-premultiplied
28          * inputs, due to the final alpha scaling it can be computed based on
29          * premultipled components:
30          *
31          *   LumA = (k1 * r / a + k2 * g / a + k3 * b / a) * a
32          *   LumA = (k1 * r + k2 * g + k3 * b)
33          */
34         unsigned luma = SkComputeLuminance(SkGetPackedR32(c),
35                                            SkGetPackedG32(c),
36                                            SkGetPackedB32(c));
37         dst[i] = SkPackARGB32(luma, 0, 0, 0);
38     }
39 }
40
41 SkColorFilter* SkLumaColorFilter::Create() { return new SkLumaColorFilter; }
42
43 SkLumaColorFilter::SkLumaColorFilter() : INHERITED() {}
44
45 SkFlattenable* SkLumaColorFilter::CreateProc(SkReadBuffer&) { return new SkLumaColorFilter; }
46
47 void SkLumaColorFilter::flatten(SkWriteBuffer&) const {}
48
49 #ifndef SK_IGNORE_TO_STRING
50 void SkLumaColorFilter::toString(SkString* str) const {
51     str->append("SkLumaColorFilter ");
52 }
53 #endif
54
55 #if SK_SUPPORT_GPU
56 class LumaColorFilterEffect : public GrFragmentProcessor {
57 public:
58     static const GrFragmentProcessor* Create() {
59         return new LumaColorFilterEffect;
60     }
61
62     const char* name() const override { return "Luminance-to-Alpha"; }
63
64     class GLSLProcessor : public GrGLSLFragmentProcessor {
65     public:
66         GLSLProcessor(const GrProcessor&) {}
67
68         static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder* b) {}
69
70         virtual void emitCode(EmitArgs& args) override {
71             if (nullptr == args.fInputColor) {
72                 args.fInputColor = "vec4(1)";
73             }
74
75             GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
76             fragBuilder->codeAppendf("\tfloat luma = dot(vec3(%f, %f, %f), %s.rgb);\n",
77                                      SK_ITU_BT709_LUM_COEFF_R,
78                                      SK_ITU_BT709_LUM_COEFF_G,
79                                      SK_ITU_BT709_LUM_COEFF_B,
80                                      args.fInputColor);
81             fragBuilder->codeAppendf("\t%s = vec4(0, 0, 0, luma);\n",
82                                      args.fOutputColor);
83
84         }
85
86     private:
87         typedef GrGLSLFragmentProcessor INHERITED;
88     };
89
90 private:
91     LumaColorFilterEffect() {
92         this->initClassID<LumaColorFilterEffect>();
93     }
94
95     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
96         return new GLSLProcessor(*this);
97     }
98
99     virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
100                                        GrProcessorKeyBuilder* b) const override {
101         GLSLProcessor::GenKey(*this, caps, b);
102     }
103
104     bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
105
106     void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
107         // The output is always black. The alpha value for the color passed in is arbitrary.
108         inout->setToOther(kRGB_GrColorComponentFlags, GrColorPackRGBA(0, 0, 0, 0),
109                           GrInvariantOutput::kWill_ReadInput);
110     }
111 };
112
113 const GrFragmentProcessor* SkLumaColorFilter::asFragmentProcessor(GrContext*) const {
114
115     return LumaColorFilterEffect::Create();
116 }
117 #endif