Home | History | Annotate | Download | only in effects
      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 #endif
     19 
     20 void 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 
     40 SkColorFilter* SkLumaColorFilter::Create() { return new SkLumaColorFilter; }
     41 
     42 SkLumaColorFilter::SkLumaColorFilter() : INHERITED() {}
     43 
     44 SkFlattenable* SkLumaColorFilter::CreateProc(SkReadBuffer&) { return new SkLumaColorFilter; }
     45 
     46 void SkLumaColorFilter::flatten(SkWriteBuffer&) const {}
     47 
     48 #ifndef SK_IGNORE_TO_STRING
     49 void SkLumaColorFilter::toString(SkString* str) const {
     50     str->append("SkLumaColorFilter ");
     51 }
     52 #endif
     53 
     54 #if SK_SUPPORT_GPU
     55 class LumaColorFilterEffect : public GrFragmentProcessor {
     56 public:
     57     static const GrFragmentProcessor* Create() {
     58         return new LumaColorFilterEffect;
     59     }
     60 
     61     const char* name() const override { return "Luminance-to-Alpha"; }
     62 
     63     class GLSLProcessor : public GrGLSLFragmentProcessor {
     64     public:
     65         static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*) {}
     66 
     67         void emitCode(EmitArgs& args) override {
     68             if (nullptr == args.fInputColor) {
     69                 args.fInputColor = "vec4(1)";
     70             }
     71 
     72             GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     73             fragBuilder->codeAppendf("\tfloat luma = dot(vec3(%f, %f, %f), %s.rgb);\n",
     74                                      SK_ITU_BT709_LUM_COEFF_R,
     75                                      SK_ITU_BT709_LUM_COEFF_G,
     76                                      SK_ITU_BT709_LUM_COEFF_B,
     77                                      args.fInputColor);
     78             fragBuilder->codeAppendf("\t%s = vec4(0, 0, 0, luma);\n",
     79                                      args.fOutputColor);
     80 
     81         }
     82 
     83     private:
     84         typedef GrGLSLFragmentProcessor INHERITED;
     85     };
     86 
     87 private:
     88     LumaColorFilterEffect() {
     89         this->initClassID<LumaColorFilterEffect>();
     90     }
     91 
     92     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
     93         return new GLSLProcessor;
     94     }
     95 
     96     virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
     97                                        GrProcessorKeyBuilder* b) const override {
     98         GLSLProcessor::GenKey(*this, caps, b);
     99     }
    100 
    101     bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
    102 
    103     void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
    104         // The output is always black. The alpha value for the color passed in is arbitrary.
    105         inout->setToOther(kRGB_GrColorComponentFlags, GrColorPackRGBA(0, 0, 0, 0),
    106                           GrInvariantOutput::kWill_ReadInput);
    107     }
    108 };
    109 
    110 const GrFragmentProcessor* SkLumaColorFilter::asFragmentProcessor(GrContext*) const {
    111 
    112     return LumaColorFilterEffect::Create();
    113 }
    114 #endif
    115