blob: fb02da5544ce61d0ffa30e815c647ac9a2ef5478 [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"
wangyix6af0c932015-07-22 10:21:17 -070012#include "gl/GrGLFragmentProcessor.h"
egdaniel2d721d32015-11-11 13:06:05 -080013#include "glsl/GrGLSLFragmentShaderBuilder.h"
14#include "glsl/GrGLSLProgramBuilder.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:
joshualittb0a8a372014-09-23 09:50:21 -070020 static GrFragmentProcessor* Create() {
bsalomon02141732015-10-21 06:57:30 -070021 return new DitherEffect;
krajcevskif461a8f2014-06-19 14:14:06 -070022 }
23
24 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:
29 DitherEffect() {
joshualitteb2a6762014-12-04 11:35:33 -080030 this->initClassID<DitherEffect>();
krajcevskif461a8f2014-06-19 14:14:06 -070031 this->setWillReadFragmentPosition();
32 }
33
wangyixb1daa862015-08-18 11:29:31 -070034 GrGLFragmentProcessor* onCreateGLInstance() const override;
35
wangyix4b3050b2015-08-04 07:59:37 -070036 void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
37
krajcevskif461a8f2014-06-19 14:14:06 -070038 // All dither effects are equal
mtklein36352bf2015-03-25 18:17:31 -070039 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
krajcevskif461a8f2014-06-19 14:14:06 -070040
mtklein36352bf2015-03-25 18:17:31 -070041 void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
egdaniel1a8ecdf2014-10-03 06:24:12 -070042
joshualittb0a8a372014-09-23 09:50:21 -070043 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
krajcevskif461a8f2014-06-19 14:14:06 -070044
joshualittb0a8a372014-09-23 09:50:21 -070045 typedef GrFragmentProcessor INHERITED;
krajcevskif461a8f2014-06-19 14:14:06 -070046};
47
egdaniel605dd0f2014-11-12 08:35:25 -080048void DitherEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
49 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
krajcevskif461a8f2014-06-19 14:14:06 -070050}
51
52//////////////////////////////////////////////////////////////////////////////
53
joshualittb0a8a372014-09-23 09:50:21 -070054GR_DEFINE_FRAGMENT_PROCESSOR_TEST(DitherEffect);
krajcevskif461a8f2014-06-19 14:14:06 -070055
bsalomonc21b09e2015-08-28 18:46:56 -070056const GrFragmentProcessor* DitherEffect::TestCreate(GrProcessorTestData*) {
krajcevskif461a8f2014-06-19 14:14:06 -070057 return DitherEffect::Create();
58}
59
60//////////////////////////////////////////////////////////////////////////////
61
joshualittb0a8a372014-09-23 09:50:21 -070062class GLDitherEffect : public GrGLFragmentProcessor {
krajcevskif461a8f2014-06-19 14:14:06 -070063public:
joshualitteb2a6762014-12-04 11:35:33 -080064 GLDitherEffect(const GrProcessor&);
krajcevskif461a8f2014-06-19 14:14:06 -070065
wangyix7c157a92015-07-22 15:08:53 -070066 virtual void emitCode(EmitArgs& args) override;
krajcevskif461a8f2014-06-19 14:14:06 -070067
68private:
joshualittb0a8a372014-09-23 09:50:21 -070069 typedef GrGLFragmentProcessor INHERITED;
krajcevskif461a8f2014-06-19 14:14:06 -070070};
71
joshualitteb2a6762014-12-04 11:35:33 -080072GLDitherEffect::GLDitherEffect(const GrProcessor&) {
krajcevskif461a8f2014-06-19 14:14:06 -070073}
74
wangyix7c157a92015-07-22 15:08:53 -070075void GLDitherEffect::emitCode(EmitArgs& args) {
egdaniel2d721d32015-11-11 13:06:05 -080076 GrGLSLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
krajcevskif461a8f2014-06-19 14:14:06 -070077 // Generate a random number based on the fragment position. For this
78 // random number generator, we use the "GLSL rand" function
79 // that seems to be floating around on the internet. It works under
80 // the assumption that sin(<big number>) oscillates with high frequency
81 // and sampling it will generate "randomness". Since we're using this
82 // for rendering and not cryptography it should be OK.
83
84 // For each channel c, add the random offset to the pixel to either bump
85 // it up or let it remain constant during quantization.
joshualitt30ba4362014-08-21 20:18:45 -070086 fsBuilder->codeAppendf("\t\tfloat r = "
bsalomon22900002014-06-24 11:16:52 -070087 "fract(sin(dot(%s.xy ,vec2(12.9898,78.233))) * 43758.5453);\n",
joshualitt30ba4362014-08-21 20:18:45 -070088 fsBuilder->fragmentPosition());
89 fsBuilder->codeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n",
wangyix7c157a92015-07-22 15:08:53 -070090 args.fOutputColor, GrGLSLExpr4(args.fInputColor).c_str());
krajcevskif461a8f2014-06-19 14:14:06 -070091}
92
93//////////////////////////////////////////////////////////////////////////////
94
wangyix4b3050b2015-08-04 07:59:37 -070095void DitherEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
egdaniel2d721d32015-11-11 13:06:05 -080096 GrProcessorKeyBuilder* b) const {
joshualitteb2a6762014-12-04 11:35:33 -080097 GLDitherEffect::GenKey(*this, caps, b);
98}
99
wangyixb1daa862015-08-18 11:29:31 -0700100GrGLFragmentProcessor* DitherEffect::onCreateGLInstance() const {
halcanary385fe4d2015-08-26 13:07:48 -0700101 return new GLDitherEffect(*this);
joshualitteb2a6762014-12-04 11:35:33 -0800102}
103
joshualittb0a8a372014-09-23 09:50:21 -0700104GrFragmentProcessor* GrDitherEffect::Create() { return DitherEffect::Create(); }