blob: 34a15651d2433f79be78189b7743aa301452b393 [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"
Brian Salomon94efbf52016-11-29 13:43:05 -050014#include "../private/GrGLSL.h"
krajcevskif461a8f2014-06-19 14:14:06 -070015
16//////////////////////////////////////////////////////////////////////////////
17
joshualittb0a8a372014-09-23 09:50:21 -070018class DitherEffect : public GrFragmentProcessor {
krajcevskif461a8f2014-06-19 14:14:06 -070019public:
bungeman06ca8ec2016-06-09 08:01:03 -070020 static sk_sp<GrFragmentProcessor> Make() {
21 return sk_sp<GrFragmentProcessor>(new DitherEffect);
krajcevskif461a8f2014-06-19 14:14:06 -070022 }
23
Mike Kleinfc6c37b2016-09-27 09:34:10 -040024 virtual ~DitherEffect() {}
krajcevskif461a8f2014-06-19 14:14:06 -070025
mtklein36352bf2015-03-25 18:17:31 -070026 const char* name() const override { return "Dither"; }
krajcevskif461a8f2014-06-19 14:14:06 -070027
krajcevskif461a8f2014-06-19 14:14:06 -070028private:
Brian Salomon587e08f2017-01-27 10:59:27 -050029 DitherEffect() : INHERITED(kNone_OptimizationFlags) { this->initClassID<DitherEffect>(); }
krajcevskif461a8f2014-06-19 14:14:06 -070030
egdaniel57d3b032015-11-13 11:57:27 -080031 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -070032
Brian Salomon94efbf52016-11-29 13:43:05 -050033 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -070034
krajcevskif461a8f2014-06-19 14:14:06 -070035 // All dither effects are equal
mtklein36352bf2015-03-25 18:17:31 -070036 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
krajcevskif461a8f2014-06-19 14:14:06 -070037
mtklein36352bf2015-03-25 18:17:31 -070038 void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
egdaniel1a8ecdf2014-10-03 06:24:12 -070039
joshualittb0a8a372014-09-23 09:50:21 -070040 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
krajcevskif461a8f2014-06-19 14:14:06 -070041
joshualittb0a8a372014-09-23 09:50:21 -070042 typedef GrFragmentProcessor INHERITED;
krajcevskif461a8f2014-06-19 14:14:06 -070043};
44
egdaniel605dd0f2014-11-12 08:35:25 -080045void DitherEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
Brian Salomon5f13fba2017-01-23 14:35:25 -050046 inout->setToUnknown();
krajcevskif461a8f2014-06-19 14:14:06 -070047}
48
49//////////////////////////////////////////////////////////////////////////////
50
joshualittb0a8a372014-09-23 09:50:21 -070051GR_DEFINE_FRAGMENT_PROCESSOR_TEST(DitherEffect);
krajcevskif461a8f2014-06-19 14:14:06 -070052
Hal Canary6f6961e2017-01-31 13:50:44 -050053#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -070054sk_sp<GrFragmentProcessor> DitherEffect::TestCreate(GrProcessorTestData*) {
55 return DitherEffect::Make();
krajcevskif461a8f2014-06-19 14:14:06 -070056}
Hal Canary6f6961e2017-01-31 13:50:44 -050057#endif
krajcevskif461a8f2014-06-19 14:14:06 -070058
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) {
cdalton85285412016-02-18 12:37:07 -080070 GrGLSLFPFragmentBuilder* 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 = "
Ethan Nicholasde4d3012017-01-19 16:58:02 -050081 "fract(sin(dot(sk_FragCoord.xy, vec2(12.9898,78.233))) * "
82 "43758.5453);\n");
egdaniel4ca2e602015-11-18 08:01:26 -080083 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
Brian Salomon94efbf52016-11-29 13:43:05 -050089void DitherEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -080090 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
bungeman06ca8ec2016-06-09 08:01:03 -070098sk_sp<GrFragmentProcessor> GrDitherEffect::Make() { return DitherEffect::Make(); }