1f461a8fdf642ba713dcdfb217534652df1eac278krajcevski/*
2f461a8fdf642ba713dcdfb217534652df1eac278krajcevski * Copyright 2014 Google Inc.
3f461a8fdf642ba713dcdfb217534652df1eac278krajcevski *
4f461a8fdf642ba713dcdfb217534652df1eac278krajcevski * Use of this source code is governed by a BSD-style license that can be
5f461a8fdf642ba713dcdfb217534652df1eac278krajcevski * found in the LICENSE file.
6f461a8fdf642ba713dcdfb217534652df1eac278krajcevski */
7f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
8f461a8fdf642ba713dcdfb217534652df1eac278krajcevski#include "GrDitherEffect.h"
9f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
10f461a8fdf642ba713dcdfb217534652df1eac278krajcevski#include "gl/GrGLEffect.h"
11f461a8fdf642ba713dcdfb217534652df1eac278krajcevski#include "gl/GrGLSL.h"
12f461a8fdf642ba713dcdfb217534652df1eac278krajcevski#include "GrTBackendEffectFactory.h"
13f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
14f461a8fdf642ba713dcdfb217534652df1eac278krajcevski#include "SkRect.h"
15f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
16f461a8fdf642ba713dcdfb217534652df1eac278krajcevski//////////////////////////////////////////////////////////////////////////////
17f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
18f461a8fdf642ba713dcdfb217534652df1eac278krajcevskiclass GLDitherEffect;
19f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
20f461a8fdf642ba713dcdfb217534652df1eac278krajcevskiclass DitherEffect : public GrEffect {
21f461a8fdf642ba713dcdfb217534652df1eac278krajcevskipublic:
22f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    static GrEffectRef* Create() {
23f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        return CreateEffectRef(AutoEffectUnref(SkNEW(DitherEffect)));
24f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    }
25f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
26f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    virtual ~DitherEffect() {};
27f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    static const char* Name() { return "Dither"; }
28f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
29f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    typedef GLDitherEffect GLEffect;
30f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
31f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
32f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
33f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
34f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        return GrTBackendEffectFactory<DitherEffect>::getInstance();
35f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    }
36f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
37f461a8fdf642ba713dcdfb217534652df1eac278krajcevskiprivate:
38f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    DitherEffect() {
39f461a8fdf642ba713dcdfb217534652df1eac278krajcevski        this->setWillReadFragmentPosition();
40f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    }
41f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
42f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // All dither effects are equal
43f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE { return true; }
44f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
45f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    GR_DECLARE_EFFECT_TEST;
46f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
47f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    typedef GrEffect INHERITED;
48f461a8fdf642ba713dcdfb217534652df1eac278krajcevski};
49f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
50f461a8fdf642ba713dcdfb217534652df1eac278krajcevskivoid DitherEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
51f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    *validFlags = 0;
52f461a8fdf642ba713dcdfb217534652df1eac278krajcevski}
53f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
54f461a8fdf642ba713dcdfb217534652df1eac278krajcevski//////////////////////////////////////////////////////////////////////////////
55f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
56f461a8fdf642ba713dcdfb217534652df1eac278krajcevskiGR_DEFINE_EFFECT_TEST(DitherEffect);
57f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
58f461a8fdf642ba713dcdfb217534652df1eac278krajcevskiGrEffectRef* DitherEffect::TestCreate(SkRandom*,
59f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                                      GrContext*,
60f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                                      const GrDrawTargetCaps&,
61f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                                      GrTexture*[]) {
62f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    return DitherEffect::Create();
63f461a8fdf642ba713dcdfb217534652df1eac278krajcevski}
64f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
65f461a8fdf642ba713dcdfb217534652df1eac278krajcevski//////////////////////////////////////////////////////////////////////////////
66f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
67f461a8fdf642ba713dcdfb217534652df1eac278krajcevskiclass GLDitherEffect : public GrGLEffect {
68f461a8fdf642ba713dcdfb217534652df1eac278krajcevskipublic:
69f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    GLDitherEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
70f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
71f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    virtual void emitCode(GrGLShaderBuilder* builder,
72f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                          const GrDrawEffect& drawEffect,
73f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                          EffectKey key,
74f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                          const char* outputColor,
75f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                          const char* inputColor,
76f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                          const TransformedCoordsArray&,
77f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                          const TextureSamplerArray&) SK_OVERRIDE;
78f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
79f461a8fdf642ba713dcdfb217534652df1eac278krajcevskiprivate:
80f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    typedef GrGLEffect INHERITED;
81f461a8fdf642ba713dcdfb217534652df1eac278krajcevski};
82f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
83f461a8fdf642ba713dcdfb217534652df1eac278krajcevskiGLDitherEffect::GLDitherEffect(const GrBackendEffectFactory& factory,
84f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                               const GrDrawEffect& drawEffect)
85f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    : INHERITED (factory) {
86f461a8fdf642ba713dcdfb217534652df1eac278krajcevski}
87f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
88f461a8fdf642ba713dcdfb217534652df1eac278krajcevskivoid GLDitherEffect::emitCode(GrGLShaderBuilder* builder,
89f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                              const GrDrawEffect& drawEffect,
90f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                              EffectKey key,
91f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                              const char* outputColor,
92f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                              const char* inputColor,
93f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                              const TransformedCoordsArray&,
94f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                              const TextureSamplerArray& samplers) {
95f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // Generate a random number based on the fragment position. For this
96f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // random number generator, we use the "GLSL rand" function
97f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // that seems to be floating around on the internet. It works under
98f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // the assumption that sin(<big number>) oscillates with high frequency
99f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // and sampling it will generate "randomness". Since we're using this
100f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // for rendering and not cryptography it should be OK.
101f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
102f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // For each channel c, add the random offset to the pixel to either bump
103f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    // it up or let it remain constant during quantization.
104f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    builder->fsCodeAppendf("\t\tfloat r = "
105160a52ba217012ed73c240f6d67b3bbf2b4879d6bsalomon                           "fract(sin(dot(%s ,vec2(12.9898,78.233))) * 43758.5453);\n",
106f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                           builder->fragmentPosition());
107aed7007e9e3ee4cdf733bf2f53531fdcd0531b25krajcevski    builder->fsCodeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n",
108f461a8fdf642ba713dcdfb217534652df1eac278krajcevski                           outputColor, GrGLSLExpr4(inputColor).c_str());
109f461a8fdf642ba713dcdfb217534652df1eac278krajcevski}
110f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
111f461a8fdf642ba713dcdfb217534652df1eac278krajcevski//////////////////////////////////////////////////////////////////////////////
112f461a8fdf642ba713dcdfb217534652df1eac278krajcevski
113f461a8fdf642ba713dcdfb217534652df1eac278krajcevskiGrEffectRef* GrDitherEffect::Create() {
114f461a8fdf642ba713dcdfb217534652df1eac278krajcevski    return DitherEffect::Create();
115f461a8fdf642ba713dcdfb217534652df1eac278krajcevski}
116