krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 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" |
joshualitt | eb2a676 | 2014-12-04 11:35:33 -0800 | [diff] [blame] | 9 | #include "GrFragmentProcessor.h" |
egdaniel | 605dd0f | 2014-11-12 08:35:25 -0800 | [diff] [blame] | 10 | #include "GrInvariantOutput.h" |
joshualitt | eb2a676 | 2014-12-04 11:35:33 -0800 | [diff] [blame] | 11 | #include "SkRect.h" |
egdaniel | 64c4728 | 2015-11-13 06:54:19 -0800 | [diff] [blame] | 12 | #include "glsl/GrGLSLFragmentProcessor.h" |
egdaniel | 2d721d3 | 2015-11-11 13:06:05 -0800 | [diff] [blame] | 13 | #include "glsl/GrGLSLFragmentShaderBuilder.h" |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 14 | |
| 15 | ////////////////////////////////////////////////////////////////////////////// |
| 16 | |
joshualitt | b0a8a37 | 2014-09-23 09:50:21 -0700 | [diff] [blame] | 17 | class DitherEffect : public GrFragmentProcessor { |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 18 | public: |
joshualitt | b0a8a37 | 2014-09-23 09:50:21 -0700 | [diff] [blame] | 19 | static GrFragmentProcessor* Create() { |
bsalomon | 0214173 | 2015-10-21 06:57:30 -0700 | [diff] [blame] | 20 | return new DitherEffect; |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 21 | } |
| 22 | |
| 23 | virtual ~DitherEffect() {}; |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 24 | |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 25 | const char* name() const override { return "Dither"; } |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 26 | |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 27 | private: |
| 28 | DitherEffect() { |
joshualitt | eb2a676 | 2014-12-04 11:35:33 -0800 | [diff] [blame] | 29 | this->initClassID<DitherEffect>(); |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 30 | this->setWillReadFragmentPosition(); |
| 31 | } |
| 32 | |
egdaniel | 57d3b03 | 2015-11-13 11:57:27 -0800 | [diff] [blame] | 33 | GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; |
wangyix | b1daa86 | 2015-08-18 11:29:31 -0700 | [diff] [blame] | 34 | |
egdaniel | 57d3b03 | 2015-11-13 11:57:27 -0800 | [diff] [blame] | 35 | void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override; |
wangyix | 4b3050b | 2015-08-04 07:59:37 -0700 | [diff] [blame] | 36 | |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 37 | // All dither effects are equal |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 38 | bool onIsEqual(const GrFragmentProcessor&) const override { return true; } |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 39 | |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 40 | void onComputeInvariantOutput(GrInvariantOutput* inout) const override; |
egdaniel | 1a8ecdf | 2014-10-03 06:24:12 -0700 | [diff] [blame] | 41 | |
joshualitt | b0a8a37 | 2014-09-23 09:50:21 -0700 | [diff] [blame] | 42 | GR_DECLARE_FRAGMENT_PROCESSOR_TEST; |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 43 | |
joshualitt | b0a8a37 | 2014-09-23 09:50:21 -0700 | [diff] [blame] | 44 | typedef GrFragmentProcessor INHERITED; |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 45 | }; |
| 46 | |
egdaniel | 605dd0f | 2014-11-12 08:35:25 -0800 | [diff] [blame] | 47 | void DitherEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const { |
| 48 | inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 49 | } |
| 50 | |
| 51 | ////////////////////////////////////////////////////////////////////////////// |
| 52 | |
joshualitt | b0a8a37 | 2014-09-23 09:50:21 -0700 | [diff] [blame] | 53 | GR_DEFINE_FRAGMENT_PROCESSOR_TEST(DitherEffect); |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 54 | |
bsalomon | c21b09e | 2015-08-28 18:46:56 -0700 | [diff] [blame] | 55 | const GrFragmentProcessor* DitherEffect::TestCreate(GrProcessorTestData*) { |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 56 | return DitherEffect::Create(); |
| 57 | } |
| 58 | |
| 59 | ////////////////////////////////////////////////////////////////////////////// |
| 60 | |
egdaniel | 64c4728 | 2015-11-13 06:54:19 -0800 | [diff] [blame] | 61 | class GLDitherEffect : public GrGLSLFragmentProcessor { |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 62 | public: |
robertphillips | 9cdb992 | 2016-02-03 12:25:40 -0800 | [diff] [blame] | 63 | void emitCode(EmitArgs& args) override; |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 64 | |
| 65 | private: |
egdaniel | 64c4728 | 2015-11-13 06:54:19 -0800 | [diff] [blame] | 66 | typedef GrGLSLFragmentProcessor INHERITED; |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 67 | }; |
| 68 | |
wangyix | 7c157a9 | 2015-07-22 15:08:53 -0700 | [diff] [blame] | 69 | void GLDitherEffect::emitCode(EmitArgs& args) { |
egdaniel | 4ca2e60 | 2015-11-18 08:01:26 -0800 | [diff] [blame] | 70 | GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 71 | // Generate a random number based on the fragment position. For this |
| 72 | // random number generator, we use the "GLSL rand" function |
| 73 | // that seems to be floating around on the internet. It works under |
| 74 | // the assumption that sin(<big number>) oscillates with high frequency |
| 75 | // and sampling it will generate "randomness". Since we're using this |
| 76 | // for rendering and not cryptography it should be OK. |
| 77 | |
| 78 | // For each channel c, add the random offset to the pixel to either bump |
| 79 | // it up or let it remain constant during quantization. |
egdaniel | 4ca2e60 | 2015-11-18 08:01:26 -0800 | [diff] [blame] | 80 | fragBuilder->codeAppendf("\t\tfloat r = " |
| 81 | "fract(sin(dot(%s.xy ,vec2(12.9898,78.233))) * 43758.5453);\n", |
| 82 | fragBuilder->fragmentPosition()); |
| 83 | fragBuilder->codeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n", |
| 84 | args.fOutputColor, GrGLSLExpr4(args.fInputColor).c_str()); |
krajcevski | f461a8f | 2014-06-19 14:14:06 -0700 | [diff] [blame] | 85 | } |
| 86 | |
| 87 | ////////////////////////////////////////////////////////////////////////////// |
| 88 | |
egdaniel | 57d3b03 | 2015-11-13 11:57:27 -0800 | [diff] [blame] | 89 | void DitherEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, |
| 90 | GrProcessorKeyBuilder* b) const { |
joshualitt | eb2a676 | 2014-12-04 11:35:33 -0800 | [diff] [blame] | 91 | GLDitherEffect::GenKey(*this, caps, b); |
| 92 | } |
| 93 | |
egdaniel | 57d3b03 | 2015-11-13 11:57:27 -0800 | [diff] [blame] | 94 | GrGLSLFragmentProcessor* DitherEffect::onCreateGLSLInstance() const { |
robertphillips | 9cdb992 | 2016-02-03 12:25:40 -0800 | [diff] [blame] | 95 | return new GLDitherEffect; |
joshualitt | eb2a676 | 2014-12-04 11:35:33 -0800 | [diff] [blame] | 96 | } |
| 97 | |
joshualitt | b0a8a37 | 2014-09-23 09:50:21 -0700 | [diff] [blame] | 98 | GrFragmentProcessor* GrDitherEffect::Create() { return DitherEffect::Create(); } |