Home | History | Annotate | Download | only in effects
      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