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
136c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#if SK_SUPPORT_GPU
146c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#include "gl/GrGLEffect.h"
156c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#include "GrContext.h"
166c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#include "GrTBackendEffectFactory.h"
176c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#endif
186c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
196c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgvoid SkLumaColorFilter::filterSpan(const SkPMColor src[], int count,
206c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org                                   SkPMColor dst[]) const {
216c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    for (int i = 0; i < count; ++i) {
226c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        SkPMColor c = src[i];
236c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
24d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org        /*
25d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org         * While LuminanceToAlpha is defined to operate on un-premultiplied
26d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org         * inputs, due to the final alpha scaling it can be computed based on
27d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org         * premultipled components:
28d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org         *
29d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org         *   LumA = (k1 * r / a + k2 * g / a + k3 * b / a) * a
30d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org         *   LumA = (k1 * r + k2 * g + k3 * b)
31d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org         */
32d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org        unsigned luma = SkComputeLuminance(SkGetPackedR32(c),
33d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org                                           SkGetPackedG32(c),
34d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org                                           SkGetPackedB32(c));
35d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org        dst[i] = SkPackARGB32(luma, 0, 0, 0);
366c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    }
376c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org}
386c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
396c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgSkColorFilter* SkLumaColorFilter::Create() {
406c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    return SkNEW(SkLumaColorFilter);
416c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org}
426c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
436c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgSkLumaColorFilter::SkLumaColorFilter()
446c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    : INHERITED() {
456c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org}
466c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
478b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkLumaColorFilter::SkLumaColorFilter(SkReadBuffer& buffer)
486c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    : INHERITED(buffer) {
496c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org}
506c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
518b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkLumaColorFilter::flatten(SkWriteBuffer&) const {
526c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org}
536c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
540f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
556c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgvoid SkLumaColorFilter::toString(SkString* str) const {
566c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    str->append("SkLumaColorFilter ");
576c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org}
586c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#endif
596c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
606c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#if SK_SUPPORT_GPU
616c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgclass LumaColorFilterEffect : public GrEffect {
626c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgpublic:
636c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    static GrEffectRef* Create() {
646c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        AutoEffectUnref effect(SkNEW(LumaColorFilterEffect));
656c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        return CreateEffectRef(effect);
666c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    }
676c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
686c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    static const char* Name() { return "Luminance-to-Alpha"; }
696c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
706c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
716c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        return GrTBackendEffectFactory<LumaColorFilterEffect>::getInstance();
726c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    }
736c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
746c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    virtual void getConstantColorComponents(GrColor* color,
756c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org                                            uint32_t* validFlags) const SK_OVERRIDE {
76d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org        // The output is always black.
77d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org        *color = GrColorPackRGBA(0, 0, 0, GrColorUnpackA(*color));
78d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org        *validFlags = kRGB_GrColorComponentFlags;
796c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    }
806c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
816c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    class GLEffect : public GrGLEffect {
826c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    public:
836c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        GLEffect(const GrBackendEffectFactory& factory,
846c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org                 const GrDrawEffect&)
856c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        : INHERITED(factory) {
866c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        }
876c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
886c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&) {
896c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org            // this class always generates the same code.
906c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org            return 0;
916c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        }
926c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
936c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        virtual void emitCode(GrGLShaderBuilder* builder,
946c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org                              const GrDrawEffect&,
956c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org                              EffectKey,
966c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org                              const char* outputColor,
976c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org                              const char* inputColor,
986c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org                              const TransformedCoordsArray&,
996c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org                              const TextureSamplerArray&) SK_OVERRIDE {
1006c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org            if (NULL == inputColor) {
101824c346b6e0e114063c1a8ad4ba7c3a669ee2cffcommit-bot@chromium.org                inputColor = "vec4(1)";
1026c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org            }
1036c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
1046c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org            builder->fsCodeAppendf("\tfloat luma = dot(vec3(%f, %f, %f), %s.rgb);\n",
1056c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org                                   SK_ITU_BT709_LUM_COEFF_R,
1066c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org                                   SK_ITU_BT709_LUM_COEFF_G,
1076c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org                                   SK_ITU_BT709_LUM_COEFF_B,
1086c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org                                   inputColor);
109d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org            builder->fsCodeAppendf("\t%s = vec4(0, 0, 0, luma);\n",
110d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org                                   outputColor);
1116c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
1126c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        }
1136c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
1146c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    private:
1156c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        typedef GrGLEffect INHERITED;
1166c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    };
1176c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
1186c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgprivate:
1196c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE {
1206c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        return true;
1216c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    }
1226c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org};
1236c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
1246c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.orgGrEffectRef* SkLumaColorFilter::asNewEffect(GrContext*) const {
1256c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    return LumaColorFilterEffect::Create();
1266c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org}
1276c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#endif
128