1/* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "GrDitherEffect.h" 9 10#include "gl/GrGLEffect.h" 11#include "gl/GrGLSL.h" 12#include "GrTBackendEffectFactory.h" 13 14#include "SkRect.h" 15 16////////////////////////////////////////////////////////////////////////////// 17 18class GLDitherEffect; 19 20class DitherEffect : public GrEffect { 21public: 22 static GrEffectRef* Create() { 23 return CreateEffectRef(AutoEffectUnref(SkNEW(DitherEffect))); 24 } 25 26 virtual ~DitherEffect() {}; 27 static const char* Name() { return "Dither"; } 28 29 typedef GLDitherEffect GLEffect; 30 31 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; 32 33 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 34 return GrTBackendEffectFactory<DitherEffect>::getInstance(); 35 } 36 37private: 38 DitherEffect() { 39 this->setWillReadFragmentPosition(); 40 } 41 42 // All dither effects are equal 43 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE { return true; } 44 45 GR_DECLARE_EFFECT_TEST; 46 47 typedef GrEffect INHERITED; 48}; 49 50void DitherEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { 51 *validFlags = 0; 52} 53 54////////////////////////////////////////////////////////////////////////////// 55 56GR_DEFINE_EFFECT_TEST(DitherEffect); 57 58GrEffectRef* DitherEffect::TestCreate(SkRandom*, 59 GrContext*, 60 const GrDrawTargetCaps&, 61 GrTexture*[]) { 62 return DitherEffect::Create(); 63} 64 65////////////////////////////////////////////////////////////////////////////// 66 67class GLDitherEffect : public GrGLEffect { 68public: 69 GLDitherEffect(const GrBackendEffectFactory&, const GrDrawEffect&); 70 71 virtual void emitCode(GrGLShaderBuilder* builder, 72 const GrDrawEffect& drawEffect, 73 EffectKey key, 74 const char* outputColor, 75 const char* inputColor, 76 const TransformedCoordsArray&, 77 const TextureSamplerArray&) SK_OVERRIDE; 78 79private: 80 typedef GrGLEffect INHERITED; 81}; 82 83GLDitherEffect::GLDitherEffect(const GrBackendEffectFactory& factory, 84 const GrDrawEffect& drawEffect) 85 : INHERITED (factory) { 86} 87 88void GLDitherEffect::emitCode(GrGLShaderBuilder* builder, 89 const GrDrawEffect& drawEffect, 90 EffectKey key, 91 const char* outputColor, 92 const char* inputColor, 93 const TransformedCoordsArray&, 94 const TextureSamplerArray& samplers) { 95 // Generate a random number based on the fragment position. For this 96 // random number generator, we use the "GLSL rand" function 97 // that seems to be floating around on the internet. It works under 98 // the assumption that sin(<big number>) oscillates with high frequency 99 // and sampling it will generate "randomness". Since we're using this 100 // for rendering and not cryptography it should be OK. 101 102 // For each channel c, add the random offset to the pixel to either bump 103 // it up or let it remain constant during quantization. 104 builder->fsCodeAppendf("\t\tfloat r = " 105 "fract(sin(dot(%s ,vec2(12.9898,78.233))) * 43758.5453);\n", 106 builder->fragmentPosition()); 107 builder->fsCodeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n", 108 outputColor, GrGLSLExpr4(inputColor).c_str()); 109} 110 111////////////////////////////////////////////////////////////////////////////// 112 113GrEffectRef* GrDitherEffect::Create() { 114 return DitherEffect::Create(); 115} 116