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 "gl/builders/GrGLProgramBuilder.h" 9 #include "GrDitherEffect.h" 10 11 #include "gl/GrGLProcessor.h" 12 #include "gl/GrGLSL.h" 13 #include "GrTBackendProcessorFactory.h" 14 15 #include "SkRect.h" 16 17 ////////////////////////////////////////////////////////////////////////////// 18 19 class GLDitherEffect; 20 21 class DitherEffect : public GrFragmentProcessor { 22 public: 23 static GrFragmentProcessor* Create() { 24 GR_CREATE_STATIC_FRAGMENT_PROCESSOR(gDitherEffect, DitherEffect, ()) 25 return SkRef(gDitherEffect); 26 } 27 28 virtual ~DitherEffect() {}; 29 static const char* Name() { return "Dither"; } 30 31 typedef GLDitherEffect GLProcessor; 32 33 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; 34 35 virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE { 36 return GrTBackendFragmentProcessorFactory<DitherEffect>::getInstance(); 37 } 38 39 private: 40 DitherEffect() { 41 this->setWillReadFragmentPosition(); 42 } 43 44 // All dither effects are equal 45 virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE { return true; } 46 47 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 48 49 typedef GrFragmentProcessor INHERITED; 50 }; 51 52 void DitherEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { 53 *validFlags = 0; 54 } 55 56 ////////////////////////////////////////////////////////////////////////////// 57 58 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(DitherEffect); 59 60 GrFragmentProcessor* DitherEffect::TestCreate(SkRandom*, 61 GrContext*, 62 const GrDrawTargetCaps&, 63 GrTexture*[]) { 64 return DitherEffect::Create(); 65 } 66 67 ////////////////////////////////////////////////////////////////////////////// 68 69 class GLDitherEffect : public GrGLFragmentProcessor { 70 public: 71 GLDitherEffect(const GrBackendProcessorFactory&, const GrProcessor&); 72 73 virtual void emitCode(GrGLProgramBuilder* builder, 74 const GrFragmentProcessor& fp, 75 const GrProcessorKey& key, 76 const char* outputColor, 77 const char* inputColor, 78 const TransformedCoordsArray&, 79 const TextureSamplerArray&) SK_OVERRIDE; 80 81 private: 82 typedef GrGLFragmentProcessor INHERITED; 83 }; 84 85 GLDitherEffect::GLDitherEffect(const GrBackendProcessorFactory& factory, 86 const GrProcessor&) 87 : INHERITED (factory) { 88 } 89 90 void GLDitherEffect::emitCode(GrGLProgramBuilder* builder, 91 const GrFragmentProcessor& fp, 92 const GrProcessorKey& key, 93 const char* outputColor, 94 const char* inputColor, 95 const TransformedCoordsArray&, 96 const TextureSamplerArray& samplers) { 97 GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 98 // Generate a random number based on the fragment position. For this 99 // random number generator, we use the "GLSL rand" function 100 // that seems to be floating around on the internet. It works under 101 // the assumption that sin(<big number>) oscillates with high frequency 102 // and sampling it will generate "randomness". Since we're using this 103 // for rendering and not cryptography it should be OK. 104 105 // For each channel c, add the random offset to the pixel to either bump 106 // it up or let it remain constant during quantization. 107 fsBuilder->codeAppendf("\t\tfloat r = " 108 "fract(sin(dot(%s.xy ,vec2(12.9898,78.233))) * 43758.5453);\n", 109 fsBuilder->fragmentPosition()); 110 fsBuilder->codeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n", 111 outputColor, GrGLSLExpr4(inputColor).c_str()); 112 } 113 114 ////////////////////////////////////////////////////////////////////////////// 115 116 GrFragmentProcessor* GrDitherEffect::Create() { return DitherEffect::Create(); } 117