blob: 43fe93769aaca848d3fd3c5df4e6a3e3e7e469a9 [file] [log] [blame]
krajcevskif461a8f2014-06-19 14:14:06 -07001/*
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"
joshualitteb2a6762014-12-04 11:35:33 -08009#include "GrFragmentProcessor.h"
egdaniel605dd0f2014-11-12 08:35:25 -080010#include "GrInvariantOutput.h"
joshualitteb2a6762014-12-04 11:35:33 -080011#include "SkRect.h"
egdaniel64c47282015-11-13 06:54:19 -080012#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel2d721d32015-11-11 13:06:05 -080013#include "glsl/GrGLSLFragmentShaderBuilder.h"
krajcevskif461a8f2014-06-19 14:14:06 -070014
15//////////////////////////////////////////////////////////////////////////////
16
joshualittb0a8a372014-09-23 09:50:21 -070017class DitherEffect : public GrFragmentProcessor {
krajcevskif461a8f2014-06-19 14:14:06 -070018public:
joshualittb0a8a372014-09-23 09:50:21 -070019 static GrFragmentProcessor* Create() {
bsalomon02141732015-10-21 06:57:30 -070020 return new DitherEffect;
krajcevskif461a8f2014-06-19 14:14:06 -070021 }
22
23 virtual ~DitherEffect() {};
krajcevskif461a8f2014-06-19 14:14:06 -070024
mtklein36352bf2015-03-25 18:17:31 -070025 const char* name() const override { return "Dither"; }
krajcevskif461a8f2014-06-19 14:14:06 -070026
krajcevskif461a8f2014-06-19 14:14:06 -070027private:
28 DitherEffect() {
joshualitteb2a6762014-12-04 11:35:33 -080029 this->initClassID<DitherEffect>();
krajcevskif461a8f2014-06-19 14:14:06 -070030 this->setWillReadFragmentPosition();
31 }
32
egdaniel57d3b032015-11-13 11:57:27 -080033 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -070034
egdaniel57d3b032015-11-13 11:57:27 -080035 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -070036
krajcevskif461a8f2014-06-19 14:14:06 -070037 // All dither effects are equal
mtklein36352bf2015-03-25 18:17:31 -070038 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
krajcevskif461a8f2014-06-19 14:14:06 -070039
mtklein36352bf2015-03-25 18:17:31 -070040 void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
egdaniel1a8ecdf2014-10-03 06:24:12 -070041
joshualittb0a8a372014-09-23 09:50:21 -070042 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
krajcevskif461a8f2014-06-19 14:14:06 -070043
joshualittb0a8a372014-09-23 09:50:21 -070044 typedef GrFragmentProcessor INHERITED;
krajcevskif461a8f2014-06-19 14:14:06 -070045};
46
egdaniel605dd0f2014-11-12 08:35:25 -080047void DitherEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
48 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
krajcevskif461a8f2014-06-19 14:14:06 -070049}
50
51//////////////////////////////////////////////////////////////////////////////
52
joshualittb0a8a372014-09-23 09:50:21 -070053GR_DEFINE_FRAGMENT_PROCESSOR_TEST(DitherEffect);
krajcevskif461a8f2014-06-19 14:14:06 -070054
bsalomonc21b09e2015-08-28 18:46:56 -070055const GrFragmentProcessor* DitherEffect::TestCreate(GrProcessorTestData*) {
krajcevskif461a8f2014-06-19 14:14:06 -070056 return DitherEffect::Create();
57}
58
59//////////////////////////////////////////////////////////////////////////////
60
egdaniel64c47282015-11-13 06:54:19 -080061class GLDitherEffect : public GrGLSLFragmentProcessor {
krajcevskif461a8f2014-06-19 14:14:06 -070062public:
robertphillips9cdb9922016-02-03 12:25:40 -080063 void emitCode(EmitArgs& args) override;
krajcevskif461a8f2014-06-19 14:14:06 -070064
65private:
egdaniel64c47282015-11-13 06:54:19 -080066 typedef GrGLSLFragmentProcessor INHERITED;
krajcevskif461a8f2014-06-19 14:14:06 -070067};
68
wangyix7c157a92015-07-22 15:08:53 -070069void GLDitherEffect::emitCode(EmitArgs& args) {
egdaniel4ca2e602015-11-18 08:01:26 -080070 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
krajcevskif461a8f2014-06-19 14:14:06 -070071 // 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.
egdaniel4ca2e602015-11-18 08:01:26 -080080 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());
krajcevskif461a8f2014-06-19 14:14:06 -070085}
86
87//////////////////////////////////////////////////////////////////////////////
88
egdaniel57d3b032015-11-13 11:57:27 -080089void DitherEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
90 GrProcessorKeyBuilder* b) const {
joshualitteb2a6762014-12-04 11:35:33 -080091 GLDitherEffect::GenKey(*this, caps, b);
92}
93
egdaniel57d3b032015-11-13 11:57:27 -080094GrGLSLFragmentProcessor* DitherEffect::onCreateGLSLInstance() const {
robertphillips9cdb9922016-02-03 12:25:40 -080095 return new GLDitherEffect;
joshualitteb2a6762014-12-04 11:35:33 -080096}
97
joshualittb0a8a372014-09-23 09:50:21 -070098GrFragmentProcessor* GrDitherEffect::Create() { return DitherEffect::Create(); }