Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / effects / GrDitherEffect.cpp
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(); }