blob: 799d970601ae34c18ea79b05b72e1456a8d04478 [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"
joshualittb0a8a372014-09-23 09:50:21 -070012#include "gl/GrGLProcessor.h"
krajcevskif461a8f2014-06-19 14:14:06 -070013#include "gl/GrGLSL.h"
joshualitteb2a6762014-12-04 11:35:33 -080014#include "gl/builders/GrGLProgramBuilder.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() {
bsalomon98b33eb2014-10-15 11:05:26 -070021 GR_CREATE_STATIC_PROCESSOR(gDitherEffect, DitherEffect, ())
bsalomon55fad7a2014-07-08 07:34:20 -070022 return SkRef(gDitherEffect);
krajcevskif461a8f2014-06-19 14:14:06 -070023 }
24
25 virtual ~DitherEffect() {};
krajcevskif461a8f2014-06-19 14:14:06 -070026
joshualitteb2a6762014-12-04 11:35:33 -080027 virtual const char* name() const SK_OVERRIDE { return "Dither"; }
krajcevskif461a8f2014-06-19 14:14:06 -070028
joshualitteb2a6762014-12-04 11:35:33 -080029 virtual void getGLProcessorKey(const GrGLCaps&, GrProcessorKeyBuilder*) const SK_OVERRIDE;
30
31 virtual GrGLFragmentProcessor* createGLInstance() const SK_OVERRIDE;
krajcevskif461a8f2014-06-19 14:14:06 -070032
33private:
34 DitherEffect() {
joshualitteb2a6762014-12-04 11:35:33 -080035 this->initClassID<DitherEffect>();
krajcevskif461a8f2014-06-19 14:14:06 -070036 this->setWillReadFragmentPosition();
37 }
38
39 // All dither effects are equal
bsalomon0e08fc12014-10-15 08:19:04 -070040 virtual bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE { return true; }
krajcevskif461a8f2014-06-19 14:14:06 -070041
egdaniel605dd0f2014-11-12 08:35:25 -080042 virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE;
egdaniel1a8ecdf2014-10-03 06:24:12 -070043
joshualittb0a8a372014-09-23 09:50:21 -070044 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
krajcevskif461a8f2014-06-19 14:14:06 -070045
joshualittb0a8a372014-09-23 09:50:21 -070046 typedef GrFragmentProcessor INHERITED;
krajcevskif461a8f2014-06-19 14:14:06 -070047};
48
egdaniel605dd0f2014-11-12 08:35:25 -080049void DitherEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
50 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
krajcevskif461a8f2014-06-19 14:14:06 -070051}
52
53//////////////////////////////////////////////////////////////////////////////
54
joshualittb0a8a372014-09-23 09:50:21 -070055GR_DEFINE_FRAGMENT_PROCESSOR_TEST(DitherEffect);
krajcevskif461a8f2014-06-19 14:14:06 -070056
joshualittb0a8a372014-09-23 09:50:21 -070057GrFragmentProcessor* DitherEffect::TestCreate(SkRandom*,
58 GrContext*,
59 const GrDrawTargetCaps&,
60 GrTexture*[]) {
krajcevskif461a8f2014-06-19 14:14:06 -070061 return DitherEffect::Create();
62}
63
64//////////////////////////////////////////////////////////////////////////////
65
joshualittb0a8a372014-09-23 09:50:21 -070066class GLDitherEffect : public GrGLFragmentProcessor {
krajcevskif461a8f2014-06-19 14:14:06 -070067public:
joshualitteb2a6762014-12-04 11:35:33 -080068 GLDitherEffect(const GrProcessor&);
krajcevskif461a8f2014-06-19 14:14:06 -070069
joshualitt15988992014-10-09 15:04:05 -070070 virtual void emitCode(GrGLFPBuilder* builder,
joshualittb0a8a372014-09-23 09:50:21 -070071 const GrFragmentProcessor& fp,
krajcevskif461a8f2014-06-19 14:14:06 -070072 const char* outputColor,
73 const char* inputColor,
74 const TransformedCoordsArray&,
75 const TextureSamplerArray&) SK_OVERRIDE;
76
77private:
joshualittb0a8a372014-09-23 09:50:21 -070078 typedef GrGLFragmentProcessor INHERITED;
krajcevskif461a8f2014-06-19 14:14:06 -070079};
80
joshualitteb2a6762014-12-04 11:35:33 -080081GLDitherEffect::GLDitherEffect(const GrProcessor&) {
krajcevskif461a8f2014-06-19 14:14:06 -070082}
83
joshualitt15988992014-10-09 15:04:05 -070084void GLDitherEffect::emitCode(GrGLFPBuilder* builder,
joshualittb0a8a372014-09-23 09:50:21 -070085 const GrFragmentProcessor& fp,
krajcevskif461a8f2014-06-19 14:14:06 -070086 const char* outputColor,
87 const char* inputColor,
88 const TransformedCoordsArray&,
89 const TextureSamplerArray& samplers) {
joshualitt15988992014-10-09 15:04:05 -070090 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
krajcevskif461a8f2014-06-19 14:14:06 -070091 // Generate a random number based on the fragment position. For this
92 // random number generator, we use the "GLSL rand" function
93 // that seems to be floating around on the internet. It works under
94 // the assumption that sin(<big number>) oscillates with high frequency
95 // and sampling it will generate "randomness". Since we're using this
96 // for rendering and not cryptography it should be OK.
97
98 // For each channel c, add the random offset to the pixel to either bump
99 // it up or let it remain constant during quantization.
joshualitt30ba4362014-08-21 20:18:45 -0700100 fsBuilder->codeAppendf("\t\tfloat r = "
bsalomon22900002014-06-24 11:16:52 -0700101 "fract(sin(dot(%s.xy ,vec2(12.9898,78.233))) * 43758.5453);\n",
joshualitt30ba4362014-08-21 20:18:45 -0700102 fsBuilder->fragmentPosition());
103 fsBuilder->codeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n",
krajcevskif461a8f2014-06-19 14:14:06 -0700104 outputColor, GrGLSLExpr4(inputColor).c_str());
105}
106
107//////////////////////////////////////////////////////////////////////////////
108
joshualitteb2a6762014-12-04 11:35:33 -0800109void DitherEffect::getGLProcessorKey(const GrGLCaps& caps,
110 GrProcessorKeyBuilder* b) const {
111 GLDitherEffect::GenKey(*this, caps, b);
112}
113
114GrGLFragmentProcessor* DitherEffect::createGLInstance() const {
115 return SkNEW_ARGS(GLDitherEffect, (*this));
116}
117
joshualittb0a8a372014-09-23 09:50:21 -0700118GrFragmentProcessor* GrDitherEffect::Create() { return DitherEffect::Create(); }