| Index: src/effects/SkLumaXfermode.cpp
|
| diff --git a/src/effects/SkLumaXfermode.cpp b/src/effects/SkLumaXfermode.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..df0a663c3b224f80934455dc176efd94b9409e23
|
| --- /dev/null
|
| +++ b/src/effects/SkLumaXfermode.cpp
|
| @@ -0,0 +1,221 @@
|
| +/*
|
| + * Copyright 2013 Google Inc.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + */
|
| +
|
| +#include "SkLumaXfermode.h"
|
| +#include "SkColorPriv.h"
|
| +#include "SkFlattenableBuffers.h"
|
| +#include "SkString.h"
|
| +
|
| +#if SK_SUPPORT_GPU
|
| +#include "gl/GrGLEffect.h"
|
| +#include "gl/GrGLEffectMatrix.h"
|
| +#include "GrContext.h"
|
| +#include "GrTBackendEffectFactory.h"
|
| +#endif
|
| +
|
| +static inline SkPMColor luma_proc(const SkPMColor a, const SkPMColor b) {
|
| + unsigned luma = SkComputeLuminance(SkGetPackedR32(b),
|
| + SkGetPackedG32(b),
|
| + SkGetPackedB32(b));
|
| + return SkAlphaMulQ(a, SkAlpha255To256(luma));
|
| +}
|
| +
|
| +template <typename T>
|
| +static inline const T* lumaOpA(SkXfermode::Mode mode,
|
| + const T* src, const T* dst) {
|
| + return SkXfermode::kSrcIn_Mode == mode ? src : dst;
|
| +}
|
| +
|
| +template <typename T>
|
| +static inline const T* lumaOpB(SkXfermode::Mode mode,
|
| + const T* src, const T* dst) {
|
| + return SkXfermode::kSrcIn_Mode == mode ? dst : src;
|
| +}
|
| +
|
| +SkXfermode* SkLumaMaskXfermode::Create(SkXfermode::Mode mode) {
|
| + if (kSrcIn_Mode == mode || kDstIn_Mode == mode) {
|
| + return SkNEW_ARGS(SkLumaMaskXfermode, (mode));
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +SkLumaMaskXfermode::SkLumaMaskXfermode(SkXfermode::Mode mode)
|
| + : fMode(mode) {
|
| + SkASSERT(kSrcIn_Mode == mode || kDstIn_Mode == mode);
|
| +}
|
| +
|
| +SkLumaMaskXfermode::SkLumaMaskXfermode(SkFlattenableReadBuffer& buffer)
|
| + : INHERITED(buffer)
|
| + , fMode((SkXfermode::Mode)buffer.readUInt()) {
|
| + SkASSERT(kSrcIn_Mode == fMode || kDstIn_Mode == fMode);
|
| +}
|
| +
|
| +void SkLumaMaskXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
|
| + INHERITED::flatten(buffer);
|
| + buffer.writeUInt(fMode);
|
| +}
|
| +
|
| +SkPMColor SkLumaMaskXfermode::xferColor(SkPMColor src, SkPMColor dst) const {
|
| + const SkPMColor* a = lumaOpA<SkPMColor>(fMode, &src, &dst);
|
| + const SkPMColor* b = lumaOpB<SkPMColor>(fMode, &src, &dst);
|
| + return luma_proc(*a, *b);
|
| +}
|
| +
|
| +void SkLumaMaskXfermode::xfer32(SkPMColor dst[], const SkPMColor src[],
|
| + int count, const SkAlpha aa[]) const {
|
| + const SkPMColor* a = lumaOpA<SkPMColor>(fMode, src, dst);
|
| + const SkPMColor* b = lumaOpB<SkPMColor>(fMode, src, dst);
|
| +
|
| + if (aa) {
|
| + for (int i = 0; i < count; ++i) {
|
| + unsigned cov = aa[i];
|
| + if (cov) {
|
| + unsigned resC = luma_proc(a[i], b[i]);
|
| + if (cov < 255) {
|
| + resC = SkAlphaMulQ(resC, SkAlpha255To256(cov));
|
| + }
|
| + dst[i] = resC;
|
| + }
|
| + }
|
| + } else {
|
| + for (int i = 0; i < count; ++i) {
|
| + dst[i] = luma_proc(a[i], b[i]);
|
| + }
|
| + }
|
| +}
|
| +
|
| +#ifdef SK_DEVELOPER
|
| +void SkLumaMaskXfermode::toString(SkString* str) const {
|
| + str->printf("SkLumaMaskXfermode: mode: %s",
|
| + fMode == kSrcIn_Mode ? "SRC_IN" : "DST_IN");
|
| +}
|
| +#endif
|
| +
|
| +#if SK_SUPPORT_GPU
|
| +//////////////////////////////////////////////////////////////////////////////
|
| +
|
| +class GrGLLumaMaskEffect : public GrGLEffect {
|
| +public:
|
| + GrGLLumaMaskEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
|
| + virtual ~GrGLLumaMaskEffect();
|
| +
|
| + virtual void emitCode(GrGLShaderBuilder*,
|
| + const GrDrawEffect&,
|
| + EffectKey,
|
| + const char* outputColor,
|
| + const char* inputColor,
|
| + const TextureSamplerArray&) SK_OVERRIDE;
|
| +
|
| + static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
|
| +
|
| +private:
|
| + typedef GrGLEffect INHERITED;
|
| +};
|
| +
|
| +class GrLumaMaskEffect : public GrEffect {
|
| +public:
|
| + static GrEffectRef* Create(SkXfermode::Mode mode) {
|
| + AutoEffectUnref effect(SkNEW_ARGS(GrLumaMaskEffect, (mode)));
|
| + return CreateEffectRef(effect);
|
| + }
|
| +
|
| + virtual ~GrLumaMaskEffect();
|
| +
|
| + typedef GrGLLumaMaskEffect GLEffect;
|
| + static const char* Name() { return "LumaMask"; }
|
| +
|
| + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
|
| + virtual void getConstantColorComponents(GrColor*, uint32_t*) const SK_OVERRIDE;
|
| +
|
| + SkXfermode::Mode getMode() const { return fMode; }
|
| +
|
| +private:
|
| + GrLumaMaskEffect(SkXfermode::Mode);
|
| +
|
| + virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
|
| +
|
| + const SkXfermode::Mode fMode;
|
| +};
|
| +
|
| +//////////////////////////////////////////////////////////////////////////////
|
| +
|
| +GrGLLumaMaskEffect::GrGLLumaMaskEffect(const GrBackendEffectFactory& factory,
|
| + const GrDrawEffect&)
|
| + : INHERITED(factory) {
|
| +}
|
| +
|
| +GrGLLumaMaskEffect::~GrGLLumaMaskEffect() {
|
| +}
|
| +
|
| +void GrGLLumaMaskEffect::emitCode(GrGLShaderBuilder* builder,
|
| + const GrDrawEffect& effect,
|
| + EffectKey key,
|
| + const char* outputColor,
|
| + const char* inputColor,
|
| + const TextureSamplerArray& samplers) {
|
| +
|
| + const GrLumaMaskEffect& lumaEffect = effect.castEffect<GrLumaMaskEffect>();
|
| + const char* dstColor = builder->dstColor();
|
| + SkASSERT(NULL != dstColor);
|
| + if (NULL == inputColor) {
|
| + inputColor = GrGLSLOnesVecf(4);
|
| + }
|
| +
|
| + const char *opA = lumaOpA<char>(lumaEffect.getMode(), inputColor, dstColor);
|
| + const char *opB = lumaOpB<char>(lumaEffect.getMode(), inputColor, dstColor);
|
| +
|
| + builder->fsCodeAppendf("\t\tfloat luma = dot(vec3(%f, %f, %f), %s.rgb); \n",
|
| + SK_ITU_BT709_LUM_COEFF_R,
|
| + SK_ITU_BT709_LUM_COEFF_G,
|
| + SK_ITU_BT709_LUM_COEFF_B,
|
| + opB);
|
| + builder->fsCodeAppendf("\t\t%s = %s * luma;\n", outputColor, opA);
|
| +}
|
| +
|
| +GrGLEffect::EffectKey GrGLLumaMaskEffect::GenKey(const GrDrawEffect& drawEffect,
|
| + const GrGLCaps&) {
|
| + const GrLumaMaskEffect& effect = drawEffect.castEffect<GrLumaMaskEffect>();
|
| + return (EffectKey)effect.getMode();
|
| +}
|
| +
|
| +//////////////////////////////////////////////////////////////////////////////
|
| +
|
| +GrLumaMaskEffect::GrLumaMaskEffect(SkXfermode::Mode mode)
|
| + : fMode(mode) {
|
| + this->setWillReadDstColor();
|
| +}
|
| +
|
| +GrLumaMaskEffect::~GrLumaMaskEffect() {
|
| +}
|
| +
|
| +const GrBackendEffectFactory& GrLumaMaskEffect::getFactory() const {
|
| + return GrTBackendEffectFactory<GrLumaMaskEffect>::getInstance();
|
| +}
|
| +
|
| +void GrLumaMaskEffect::getConstantColorComponents(GrColor*, uint32_t *validFlags) const {
|
| + *validFlags = 0;
|
| +}
|
| +
|
| +bool GrLumaMaskEffect::onIsEqual(const GrEffect& sBase) const {
|
| + return fMode == CastEffect<GrLumaMaskEffect>(sBase).fMode;
|
| +}
|
| +
|
| +//////////////////////////////////////////////////////////////////////////////
|
| +
|
| +bool SkLumaMaskXfermode::asNewEffectOrCoeff(GrContext*, GrEffectRef** effect,
|
| + Coeff*, Coeff*,
|
| + GrTexture* background) const {
|
| + // No background texture support.
|
| + if (effect && !background) {
|
| + *effect = GrLumaMaskEffect::Create(fMode);
|
| + return true;
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| +#endif // SK_SUPPORT_GPU
|
|
|