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 18 class GLDitherEffect; 19 20 class DitherEffect : public GrEffect { 21 public: 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 37 private: 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 50 void DitherEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { 51 *validFlags = 0; 52 } 53 54 ////////////////////////////////////////////////////////////////////////////// 55 56 GR_DEFINE_EFFECT_TEST(DitherEffect); 57 58 GrEffectRef* DitherEffect::TestCreate(SkRandom*, 59 GrContext*, 60 const GrDrawTargetCaps&, 61 GrTexture*[]) { 62 return DitherEffect::Create(); 63 } 64 65 ////////////////////////////////////////////////////////////////////////////// 66 67 class GLDitherEffect : public GrGLEffect { 68 public: 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 79 private: 80 typedef GrGLEffect INHERITED; 81 }; 82 83 GLDitherEffect::GLDitherEffect(const GrBackendEffectFactory& factory, 84 const GrDrawEffect& drawEffect) 85 : INHERITED (factory) { 86 } 87 88 void 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 113 GrEffectRef* GrDitherEffect::Create() { 114 return DitherEffect::Create(); 115 } 116