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