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