SkLumaColorFilter.cpp revision 6c1ee2d4e727357451c8a6fcf4a08e75890b5d6d
16c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org/* 26c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * Copyright 2013 Google Inc. 36c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * 46c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be 56c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * found in the LICENSE file. 66c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org */ 76c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 86c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#include "SkLumaColorFilter.h" 96c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 106c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#include "SkColorPriv.h" 116c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#include "SkString.h" 126c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#include "SkUnPreMultiply.h" 136c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 146c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#if SK_SUPPORT_GPU 156c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#include "gl/GrGLEffect.h" 166c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#include "GrContext.h" 176c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#include "GrTBackendEffectFactory.h" 186c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#endif 196c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 206c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgvoid SkLumaColorFilter::filterSpan(const SkPMColor src[], int count, 216c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org SkPMColor dst[]) const { 226c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable(); 236c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 246c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org for (int i = 0; i < count; ++i) { 256c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org SkPMColor c = src[i]; 266c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 276c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org unsigned r = SkGetPackedR32(c); 286c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org unsigned g = SkGetPackedG32(c); 296c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org unsigned b = SkGetPackedB32(c); 306c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org unsigned a = SkGetPackedA32(c); 316c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 326c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org // No need to do anything for white (luminance == 1.0) 336c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org if (a != r || a != g || a != b) { 346c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org /* 356c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * To avoid un-premultiplying multiple components, we can start 366c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * with the luminance computed in PM space: 376c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * 386c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * Lum = i * (r / a) + j * (g / a) + k * (b / a) 396c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * Lum = (i * r + j * g + k * b) / a 406c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * Lum = Lum'(PM) / a 416c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * 426c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * Then the filter function is: 436c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * 446c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * C' = [ Lum * a, Lum * r, Lum * g, Lum * b ] 456c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * 466c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * which is equivalent to: 476c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * 486c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org * C' = [ Lum'(PM), Lum * r, Lum * g, Lum * b ] 496c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org */ 506c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org unsigned pm_lum = SkComputeLuminance(r, g, b); 516c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org unsigned lum = SkUnPreMultiply::ApplyScale(table[a], pm_lum); 526c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 536c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org c = SkPackARGB32(pm_lum, 546c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org SkMulDiv255Round(r, lum), 556c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org SkMulDiv255Round(g, lum), 566c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org SkMulDiv255Round(b, lum)); 576c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org } 586c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 596c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org dst[i] = c; 606c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org } 616c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org} 626c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 636c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgSkColorFilter* SkLumaColorFilter::Create() { 646c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org return SkNEW(SkLumaColorFilter); 656c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org} 666c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 676c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgSkLumaColorFilter::SkLumaColorFilter() 686c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org : INHERITED() { 696c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org} 706c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 716c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgSkLumaColorFilter::SkLumaColorFilter(SkFlattenableReadBuffer& buffer) 726c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org : INHERITED(buffer) { 736c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org} 746c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 756c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgvoid SkLumaColorFilter::flatten(SkFlattenableWriteBuffer&) const { 766c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org} 776c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 786c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#ifdef SK_DEVELOPER 796c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgvoid SkLumaColorFilter::toString(SkString* str) const { 806c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org str->append("SkLumaColorFilter "); 816c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org} 826c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#endif 836c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 846c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#if SK_SUPPORT_GPU 856c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgclass LumaColorFilterEffect : public GrEffect { 866c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgpublic: 876c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org static GrEffectRef* Create() { 886c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org AutoEffectUnref effect(SkNEW(LumaColorFilterEffect)); 896c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org return CreateEffectRef(effect); 906c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org } 916c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 926c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org static const char* Name() { return "Luminance-to-Alpha"; } 936c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 946c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 956c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org return GrTBackendEffectFactory<LumaColorFilterEffect>::getInstance(); 966c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org } 976c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 986c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org virtual void getConstantColorComponents(GrColor* color, 996c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org uint32_t* validFlags) const SK_OVERRIDE { 1006c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org *validFlags = 0; 1016c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org } 1026c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 1036c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org class GLEffect : public GrGLEffect { 1046c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org public: 1056c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org GLEffect(const GrBackendEffectFactory& factory, 1066c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org const GrDrawEffect&) 1076c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org : INHERITED(factory) { 1086c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org } 1096c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 1106c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&) { 1116c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org // this class always generates the same code. 1126c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org return 0; 1136c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org } 1146c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 1156c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org virtual void emitCode(GrGLShaderBuilder* builder, 1166c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org const GrDrawEffect&, 1176c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org EffectKey, 1186c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org const char* outputColor, 1196c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org const char* inputColor, 1206c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org const TransformedCoordsArray&, 1216c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org const TextureSamplerArray&) SK_OVERRIDE { 1226c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org if (NULL == inputColor) { 1236c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org inputColor = GrGLSLOnesVecf(4); 1246c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org } 1256c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 1266c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org // The max() is to guard against 0 / 0 during unpremul when the incoming color is 1276c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org // transparent black. 1286c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org builder->fsCodeAppendf("\tfloat nonZeroAlpha = max(%s.a, 0.00001);\n", inputColor); 1296c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org builder->fsCodeAppendf("\tfloat luma = dot(vec3(%f, %f, %f), %s.rgb);\n", 1306c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org SK_ITU_BT709_LUM_COEFF_R, 1316c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org SK_ITU_BT709_LUM_COEFF_G, 1326c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org SK_ITU_BT709_LUM_COEFF_B, 1336c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org inputColor); 1346c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org builder->fsCodeAppendf("\t%s = vec4(%s.rgb * luma / nonZeroAlpha, luma);\n", 1356c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org outputColor, inputColor); 1366c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 1376c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org } 1386c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 1396c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org private: 1406c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org typedef GrGLEffect INHERITED; 1416c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org }; 1426c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 1436c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgprivate: 1446c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE { 1456c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org return true; 1466c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org } 1476c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org}; 1486c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org 1496c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgGrEffectRef* SkLumaColorFilter::asNewEffect(GrContext*) const { 1506c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org return LumaColorFilterEffect::Create(); 1516c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org} 1526c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#endif 153