Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(166)

Unified Diff: src/effects/SkColorFilters.cpp

Issue 25023003: Implement color filter as GrGLEffect (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/effects/SkColorFilters.cpp
diff --git a/src/effects/SkColorFilters.cpp b/src/effects/SkColorFilters.cpp
index 41a201ef39559fc232e10319c3a9e65f20c39c8c..9bc3e853025293da225c54dbe3f87bb15f570c51 100644
--- a/src/effects/SkColorFilters.cpp
+++ b/src/effects/SkColorFilters.cpp
@@ -11,6 +11,7 @@
#include "SkColorFilter.h"
#include "SkColorPriv.h"
#include "SkFlattenableBuffers.h"
+#include "SkGr.h"
#include "SkUtils.h"
#include "SkString.h"
@@ -85,6 +86,9 @@ public:
}
#endif
+#if SK_SUPPORT_GPU
+ virtual GrEffectRef* asNewEffect(GrContext*) const SK_OVERRIDE;
+#endif
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
protected:
@@ -117,6 +121,248 @@ private:
typedef SkColorFilter INHERITED;
};
+///////////////////////////////////////////////////////////////////////////////
+#if SK_SUPPORT_GPU
+#include "GrEffect.h"
+#include "GrEffectUnitTest.h"
+#include "GrTBackendEffectFactory.h"
+#include "gl/GrGLEffect.h"
+#include "gl/GrGLEffectMatrix.h"
+
+namespace {
+
+/**
+ * Create a blend_coeff * value string to be used in shader code. Sets empty
+ * string if result is trivially zero.
+ */
+inline void blend_term_string(SkString* str, SkXfermode::Coeff coeff,
+ const char* src, const char* dst,
+ const char* value) {
+ switch (coeff) {
+ case SkXfermode::kZero_Coeff: /** 0 */
+ *str = "";
+ //SkASSERT(NULL == dst);
+ break;
+ case SkXfermode::kOne_Coeff: /** 1 */
+ *str = value;
+ //SkASSERT(NULL == dst);
+ break;
+ case SkXfermode::kSC_Coeff:
+ str->printf("(%s * %s)", src, value);
+ //SkASSERT(NULL == dst);
+ break;
+ case SkXfermode::kISC_Coeff:
+ str->printf("((%s - %s) * %s)", GrGLSLExpr<4>::onesStr(), src, value);
+ //SkASSERT(NULL == dst);
+ break;
+ case SkXfermode::kDC_Coeff:
+ str->printf("(%s * %s)", dst, value);
+ break;
+ case SkXfermode::kIDC_Coeff:
+ str->printf("((%s - %s) * %s)", GrGLSLExpr<4>::onesStr(), dst, value);
+ break;
+ case SkXfermode::kSA_Coeff: /** src alpha */
+ str->printf("(%s.a * %s)", src, value);
+ //SkASSERT(NULL == dst);
+ break;
+ case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */
+ str->printf("((1.0 - %s.a) * %s)", src, value);
+ //SkASSERT(NULL == dst);
+ break;
+ case SkXfermode::kDA_Coeff: /** dst alpha */
+ str->printf("(%s.a * %s)", dst, value);
+ break;
+ case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */
+ str->printf("((1.0 - %s.a) * %s)", dst, value);
+ break;
+ default:
+ GrCrash("Unexpected xfer coeff.");
+ break;
+ }
+}
+/**
+ * Adds a line to the fragment shader code which modifies the color by
+ * the specified color filter.
+ */
+GrGLSLExpr<4> add_color_filter(SkXfermode::Mode mode,
+ const char* filterColor,
+ const char* inColor) {
+ SkXfermode::Coeff colorCoeff;
+ SkXfermode::Coeff filterColorCoeff;
+ SkAssertResult(SkXfermode::ModeAsCoeff(mode, &filterColorCoeff, &colorCoeff));
+
+ SkString colorStr, constStr;
+ blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor);
+ blend_term_string(&constStr, filterColorCoeff, filterColor, inColor, filterColor);
+
+ SkASSERT(!(colorStr.isEmpty() && constStr.isEmpty()));
+
+ if (colorStr.isEmpty()) {
+ return constStr;
+ } else if (constStr.isEmpty()) {
+ return colorStr;
+ }
+ return GrGLSLAddf<4,4>(colorStr, constStr);
+}
+}
+
+/**
+ */
+class ModeColorFilterEffect : public GrEffect {
+public:
+ static GrEffectRef* Create(const GrColor& c, SkXfermode::Mode mode) {
+ AutoEffectUnref effect(SkNEW_ARGS(ModeColorFilterEffect, (c, mode)));
+ return CreateEffectRef(effect);
+ }
+
+ virtual void getConstantColorComponents(GrColor* color,
+ uint32_t* validFlags) const SK_OVERRIDE {
+ if (SkXfermode::kDst_Mode != fMode) {
+ *validFlags = 0;
+ }
+ }
+
+ virtual bool getWillUseInputColor() const {
+ SkXfermode::Coeff dstCoeff;
+ SkXfermode::Coeff srcCoeff;
+ SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
+
+ if (SkXfermode::kZero_Coeff == dstCoeff) {
+ switch (srcCoeff) {
+ // these all read the dst
+ case SkXfermode::kDC_Coeff:
+ case SkXfermode::kIDC_Coeff:
+ case SkXfermode::kDA_Coeff:
+ case SkXfermode::kIDA_Coeff:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool getWillUseFilterColor() const {
+ SkXfermode::Coeff dstCoeff;
+ SkXfermode::Coeff srcCoeff;
+ SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
+ if (SkXfermode::kZero_Coeff == srcCoeff) {
+ switch (dstCoeff) {
+ // these all read the src
+ case SkXfermode::kSC_Coeff:
+ case SkXfermode::kISC_Coeff:
+ case SkXfermode::kSA_Coeff:
+ case SkXfermode::kISA_Coeff:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return true;
+ }
+
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
+ return GrTBackendEffectFactory<ModeColorFilterEffect>::getInstance();
+ }
+
+ static const char* Name() { return "ModeColorFilterEffect"; }
+
+ SkXfermode::Mode mode() const { return fMode; }
+ GrColor color() const { return fColor; }
+
+ class GLEffect : public GrGLEffect {
+ public:
+ GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
+ : GrGLEffect(factory) {
+ }
+
+ virtual void emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TextureSamplerArray& samplers) SK_OVERRIDE {
+ SkXfermode::Mode mode = drawEffect.castEffect<ModeColorFilterEffect>().mode();
+
+ if (SkXfermode::kDst_Mode != mode) {
+ const char* colorFilterColorUniName = NULL;
+ if (drawEffect.castEffect<ModeColorFilterEffect>().getWillUseFilterColor()) {
+ fFilterColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType, "FilterColor",
+ &colorFilterColorUniName);
+ }
+
+ const char* color;
+ // FIXME: special case for black and white.
+ color = inputColor;
+ GrGLSLExpr<4> filter = add_color_filter(mode, colorFilterColorUniName, color);
+ builder->fsCodeAppendf("\t%s = %s;\n", outputColor, filter.c_str());
+ } else {
+ builder->fsCodeAppendf("\t%s = %s;\n", outputColor, inputColor);
+ }
+ }
+
+ static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
+ const ModeColorFilterEffect& colorModeFilter = drawEffect.castEffect<ModeColorFilterEffect>();
+
+ EffectKey modeKey = colorModeFilter.mode();
+ return modeKey;
+ }
+
+ virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) SK_OVERRIDE {
+ if (fFilterColorUni.isValid()) {
+ const ModeColorFilterEffect& colorModeFilter = drawEffect.castEffect<ModeColorFilterEffect>();
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(colorModeFilter.color(), c);
+ uman.set4fv(fFilterColorUni, 0, 1, c);
+ }
+ }
+
+ private:
+
+ static const GrEffect::CoordsType kCoordsType = GrEffect::kLocal_CoordsType;
+ GrGLUniformManager::UniformHandle fFilterColorUni;
+ typedef GrGLEffect INHERITED;
+ };
+
+ GR_DECLARE_EFFECT_TEST;
+
+private:
+ ModeColorFilterEffect(GrColor color, SkXfermode::Mode mode)
+ : fMode(mode),
+ fColor(color) {
+ }
+
+ virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
+ const ModeColorFilterEffect& s = CastEffect<ModeColorFilterEffect>(other);
+ return fMode == s.fMode && fColor == s.fColor;
+ }
+
+ SkXfermode::Mode fMode;
+ GrColor fColor;
+
+ typedef GrEffect INHERITED;
+};
+
+GR_DEFINE_EFFECT_TEST(ModeColorFilterEffect);
+GrEffectRef* ModeColorFilterEffect::TestCreate(SkRandom* rand,
+ GrContext*,
+ const GrDrawTargetCaps&,
+ GrTexture*[]) {
+ int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
+ GrColor color = rand->nextU();
+ static AutoEffectUnref gEffect(SkNEW_ARGS(ModeColorFilterEffect, (color, static_cast<SkXfermode::Mode>(mode))));
+ return CreateEffectRef(gEffect);
+}
+
+#endif
+
+GrEffectRef* SkModeColorFilter::asNewEffect(GrContext*) const {
+ return ModeColorFilterEffect::Create(SkColor2GrColor(fColor), fMode);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
class Src_SkModeColorFilter : public SkModeColorFilter {
public:
Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {}
« no previous file with comments | « include/gpu/GrPaint.h ('k') | src/gpu/GrDrawState.h » ('j') | src/gpu/gl/GrGLProgram.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698