| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 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* validFla
     gs) 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 #if GR_DITHER_RANDOM | 
|  | 96     // Generate a random number based on the fragment position. For this | 
|  | 97     // random number generator, we use the "GLSL rand" function | 
|  | 98     // that seems to be floating around on the internet. It works under | 
|  | 99     // the assumption that sin(<big number>) oscillates with high frequency | 
|  | 100     // and sampling it will generate "randomness". Since we're using this | 
|  | 101     // for rendering and not cryptography it should be OK. | 
|  | 102 | 
|  | 103     // for each channel c: | 
|  | 104     // 1. Compute quantized colors [low, high] that c is between | 
|  | 105     // 2. Pick high by flipping a coin weighted by (c - low) | 
|  | 106     builder->fsCodeAppendf("\t\tfloat r = " | 
|  | 107                            "fract(sin(dot(%s.xy ,vec2(12.9898,78.233))) * 43758.
     5453);\n", | 
|  | 108                            builder->fragmentPosition()); | 
|  | 109 | 
|  | 110     // For each channel, weight the neighboring pixel values based on thier | 
|  | 111     // distance from the input channel | 
|  | 112     static const char *kSuffixes[] = { "r", "g", "b" }; | 
|  | 113     static const int kNumSuffixes = SK_ARRAY_COUNT(kSuffixes); | 
|  | 114     for (int i = 0; i < kNumSuffixes; ++i) { | 
|  | 115         builder->fsCodeAppendf("\t\tfloat dithered_%s;\n", kSuffixes[i]); | 
|  | 116         builder->fsCodeAppendf("\t\t{\n"); | 
|  | 117         builder->fsCodeAppendf("\t\t\tfloat channel = 255.0f * %s.%s;\n", | 
|  | 118                                inputColor, kSuffixes[i]); | 
|  | 119         builder->fsCodeAppendf("\t\t\tfloat low = floor(channel);\n"); | 
|  | 120         builder->fsCodeAppendf("\t\t\tfloat c = channel-low;\n"); | 
|  | 121         builder->fsCodeAppendf("\t\t\tfloat high = low + 1;\n"); | 
|  | 122         builder->fsCodeAppendf("\t\t\tfloat t = float(c > r);\n"); | 
|  | 123         builder->fsCodeAppendf("\t\t\tdithered_%s = (low*(1-t) + high*t)/255.0f;
     \n", kSuffixes[i]); | 
|  | 124         builder->fsCodeAppendf("\t\t}\n"); | 
|  | 125     } | 
|  | 126 | 
|  | 127     builder->fsCodeAppendf("\t\t%s = vec4(", outputColor); | 
|  | 128     for (int i = 0; i < kNumSuffixes; ++i) { | 
|  | 129         builder->fsCodeAppendf("dithered_%s%s", kSuffixes[i], (i < kNumSuffixes)
     ? ", " : ""); | 
|  | 130     } | 
|  | 131     builder->fsCodeAppendf("%s.a);\n", inputColor); | 
|  | 132 #else | 
|  | 133     builder->fsCodeAppendf("\t\tfloat dither[4] = float[4](\n"); | 
|  | 134     builder->fsCodeAppendf("\t\t\t0.000784314, 0.00235294, 0.00313725, 0.0015686
     3);\n"); | 
|  | 135     builder->fsCodeAppendf("\t\tint x = int(%s.x + 0.5) & 1;\n", builder->fragme
     ntPosition()); | 
|  | 136     builder->fsCodeAppendf("\t\tint y = int(%s.y + 0.5) & 1;\n", builder->fragme
     ntPosition()); | 
|  | 137     builder->fsCodeAppendf("\t\tfloat d = dither[y*2+x];\n"); | 
|  | 138     builder->fsCodeAppendf("\t\t%s = vec4(d, d, d, 0) + %s;\n", | 
|  | 139                            outputColor, inputColor); | 
|  | 140 #endif | 
|  | 141 } | 
|  | 142 | 
|  | 143 ////////////////////////////////////////////////////////////////////////////// | 
|  | 144 | 
|  | 145 GrEffectRef* GrDitherEffect::Create() { | 
|  | 146     return DitherEffect::Create(); | 
|  | 147 } | 
| OLD | NEW | 
|---|