diff options
Diffstat (limited to 'chromium/third_party/skia/src/gpu/effects/GrDitherEffect.cpp')
-rw-r--r-- | chromium/third_party/skia/src/gpu/effects/GrDitherEffect.cpp | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/chromium/third_party/skia/src/gpu/effects/GrDitherEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrDitherEffect.cpp new file mode 100644 index 00000000000..7409e5ff715 --- /dev/null +++ b/chromium/third_party/skia/src/gpu/effects/GrDitherEffect.cpp @@ -0,0 +1,115 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrDitherEffect.h" + +#include "gl/GrGLEffect.h" +#include "gl/GrGLSL.h" +#include "GrTBackendEffectFactory.h" + +#include "SkRect.h" + +////////////////////////////////////////////////////////////////////////////// + +class GLDitherEffect; + +class DitherEffect : public GrEffect { +public: + static GrEffectRef* Create() { + return CreateEffectRef(AutoEffectUnref(SkNEW(DitherEffect))); + } + + virtual ~DitherEffect() {}; + static const char* Name() { return "Dither"; } + + typedef GLDitherEffect GLEffect; + + virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; + + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { + return GrTBackendEffectFactory<DitherEffect>::getInstance(); + } + +private: + DitherEffect() { + this->setWillReadFragmentPosition(); + } + + // All dither effects are equal + virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE { return true; } + + GR_DECLARE_EFFECT_TEST; + + typedef GrEffect INHERITED; +}; + +void DitherEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { + *validFlags = 0; +} + +////////////////////////////////////////////////////////////////////////////// + +GR_DEFINE_EFFECT_TEST(DitherEffect); + +GrEffectRef* DitherEffect::TestCreate(SkRandom*, + GrContext*, + const GrDrawTargetCaps&, + GrTexture*[]) { + return DitherEffect::Create(); +} + +////////////////////////////////////////////////////////////////////////////// + +class GLDitherEffect : public GrGLEffect { +public: + GLDitherEffect(const GrBackendEffectFactory&, const GrDrawEffect&); + + virtual void emitCode(GrGLShaderBuilder* builder, + const GrDrawEffect& drawEffect, + EffectKey key, + const char* outputColor, + const char* inputColor, + const TransformedCoordsArray&, + const TextureSamplerArray&) SK_OVERRIDE; + +private: + typedef GrGLEffect INHERITED; +}; + +GLDitherEffect::GLDitherEffect(const GrBackendEffectFactory& factory, + const GrDrawEffect& drawEffect) + : INHERITED (factory) { +} + +void GLDitherEffect::emitCode(GrGLShaderBuilder* builder, + const GrDrawEffect& drawEffect, + EffectKey key, + const char* outputColor, + const char* inputColor, + const TransformedCoordsArray&, + const TextureSamplerArray& samplers) { + // Generate a random number based on the fragment position. For this + // random number generator, we use the "GLSL rand" function + // that seems to be floating around on the internet. It works under + // the assumption that sin(<big number>) oscillates with high frequency + // and sampling it will generate "randomness". Since we're using this + // for rendering and not cryptography it should be OK. + + // For each channel c, add the random offset to the pixel to either bump + // it up or let it remain constant during quantization. + builder->fsCodeAppendf("\t\tfloat r = " + "fract(sin(dot(%s.xy ,vec2(12.9898,78.233))) * 43758.5453);\n", + builder->fragmentPosition()); + builder->fsCodeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n", + outputColor, GrGLSLExpr4(inputColor).c_str()); +} + +////////////////////////////////////////////////////////////////////////////// + +GrEffectRef* GrDitherEffect::Create() { + return DitherEffect::Create(); +} |