Line data Source code
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 : #include "GrFragmentProcessor.h"
10 : #include "SkRect.h"
11 : #include "glsl/GrGLSLFragmentProcessor.h"
12 : #include "glsl/GrGLSLFragmentShaderBuilder.h"
13 : #include "../private/GrGLSL.h"
14 :
15 : //////////////////////////////////////////////////////////////////////////////
16 :
17 : class DitherEffect : public GrFragmentProcessor {
18 : public:
19 0 : static sk_sp<GrFragmentProcessor> Make() {
20 0 : return sk_sp<GrFragmentProcessor>(new DitherEffect);
21 : }
22 :
23 0 : ~DitherEffect() override {}
24 :
25 0 : const char* name() const override { return "Dither"; }
26 :
27 : private:
28 0 : DitherEffect() : INHERITED(kNone_OptimizationFlags) { this->initClassID<DitherEffect>(); }
29 :
30 : GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
31 :
32 : void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
33 :
34 : // All dither effects are equal
35 0 : bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
36 :
37 : GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
38 :
39 : typedef GrFragmentProcessor INHERITED;
40 : };
41 :
42 : //////////////////////////////////////////////////////////////////////////////
43 :
44 : GR_DEFINE_FRAGMENT_PROCESSOR_TEST(DitherEffect);
45 :
46 : #if GR_TEST_UTILS
47 0 : sk_sp<GrFragmentProcessor> DitherEffect::TestCreate(GrProcessorTestData*) {
48 0 : return DitherEffect::Make();
49 : }
50 : #endif
51 :
52 : //////////////////////////////////////////////////////////////////////////////
53 :
54 0 : class GLDitherEffect : public GrGLSLFragmentProcessor {
55 : public:
56 : void emitCode(EmitArgs& args) override;
57 :
58 : private:
59 : typedef GrGLSLFragmentProcessor INHERITED;
60 : };
61 :
62 0 : void GLDitherEffect::emitCode(EmitArgs& args) {
63 0 : GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
64 : // Generate a random number based on the fragment position. For this
65 : // random number generator, we use the "GLSL rand" function
66 : // that seems to be floating around on the internet. It works under
67 : // the assumption that sin(<big number>) oscillates with high frequency
68 : // and sampling it will generate "randomness". Since we're using this
69 : // for rendering and not cryptography it should be OK.
70 :
71 : // For each channel c, add the random offset to the pixel to either bump
72 : // it up or let it remain constant during quantization.
73 0 : fragBuilder->codeAppendf("\t\tfloat r = "
74 : "fract(sin(dot(sk_FragCoord.xy, vec2(12.9898,78.233))) * "
75 0 : "43758.5453);\n");
76 0 : fragBuilder->codeAppendf("\t\t%s = clamp((1.0/255.0) * vec4(r, r, r, r) + %s, 0, 1);\n",
77 0 : args.fOutputColor, GrGLSLExpr4(args.fInputColor).c_str());
78 0 : }
79 :
80 : //////////////////////////////////////////////////////////////////////////////
81 :
82 0 : void DitherEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
83 : GrProcessorKeyBuilder* b) const {
84 0 : GLDitherEffect::GenKey(*this, caps, b);
85 0 : }
86 :
87 0 : GrGLSLFragmentProcessor* DitherEffect::onCreateGLSLInstance() const {
88 0 : return new GLDitherEffect;
89 : }
90 :
91 0 : sk_sp<GrFragmentProcessor> GrDitherEffect::Make() { return DitherEffect::Make(); }
|