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 "SkRasterPipeline.h" 12#include "SkString.h" 13 14#if SK_SUPPORT_GPU 15#include "GrContext.h" 16#include "glsl/GrGLSLFragmentProcessor.h" 17#include "glsl/GrGLSLFragmentShaderBuilder.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 40bool SkLumaColorFilter::onAppendStages(SkRasterPipeline* p, 41 SkColorSpace* dst, 42 SkArenaAlloc* scratch, 43 bool shaderIsOpaque) const { 44 p->append(SkRasterPipeline::luminance_to_alpha); 45 return true; 46} 47 48sk_sp<SkColorFilter> SkLumaColorFilter::Make() { 49 return sk_sp<SkColorFilter>(new SkLumaColorFilter); 50} 51 52SkLumaColorFilter::SkLumaColorFilter() : INHERITED() {} 53 54sk_sp<SkFlattenable> SkLumaColorFilter::CreateProc(SkReadBuffer&) { 55 return Make(); 56} 57 58void SkLumaColorFilter::flatten(SkWriteBuffer&) const {} 59 60#ifndef SK_IGNORE_TO_STRING 61void SkLumaColorFilter::toString(SkString* str) const { 62 str->append("SkLumaColorFilter "); 63} 64#endif 65 66#if SK_SUPPORT_GPU 67class LumaColorFilterEffect : public GrFragmentProcessor { 68public: 69 static sk_sp<GrFragmentProcessor> Make() { 70 return sk_sp<GrFragmentProcessor>(new LumaColorFilterEffect); 71 } 72 73 const char* name() const override { return "Luminance-to-Alpha"; } 74 75 class GLSLProcessor : public GrGLSLFragmentProcessor { 76 public: 77 static void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*) {} 78 79 void emitCode(EmitArgs& args) override { 80 if (nullptr == args.fInputColor) { 81 args.fInputColor = "vec4(1)"; 82 } 83 84 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 85 fragBuilder->codeAppendf("\tfloat luma = dot(vec3(%f, %f, %f), %s.rgb);\n", 86 SK_ITU_BT709_LUM_COEFF_R, 87 SK_ITU_BT709_LUM_COEFF_G, 88 SK_ITU_BT709_LUM_COEFF_B, 89 args.fInputColor); 90 fragBuilder->codeAppendf("\t%s = vec4(0, 0, 0, luma);\n", 91 args.fOutputColor); 92 93 } 94 95 private: 96 typedef GrGLSLFragmentProcessor INHERITED; 97 }; 98 99private: 100 LumaColorFilterEffect() : INHERITED(kConstantOutputForConstantInput_OptimizationFlag) { 101 this->initClassID<LumaColorFilterEffect>(); 102 } 103 104 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { 105 return new GLSLProcessor; 106 } 107 108 virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps, 109 GrProcessorKeyBuilder* b) const override { 110 GLSLProcessor::GenKey(*this, caps, b); 111 } 112 113 bool onIsEqual(const GrFragmentProcessor&) const override { return true; } 114 115 GrColor4f constantOutputForConstantInput(GrColor4f input) const override { 116 float luma = SK_ITU_BT709_LUM_COEFF_R * input.fRGBA[0] + 117 SK_ITU_BT709_LUM_COEFF_G * input.fRGBA[1] + 118 SK_ITU_BT709_LUM_COEFF_B * input.fRGBA[2]; 119 return GrColor4f(0, 0, 0, luma); 120 } 121 122 typedef GrFragmentProcessor INHERITED; 123}; 124 125sk_sp<GrFragmentProcessor> SkLumaColorFilter::asFragmentProcessor(GrContext*, SkColorSpace*) const { 126 return LumaColorFilterEffect::Make(); 127} 128#endif 129