blob: ce8c4716653911dad53a8b91a71f3f9b720782d3 [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
joshualitt30ba4362014-08-21 20:18:45 -07008#include "gl/builders/GrGLProgramBuilder.h"
krajcevskif461a8f2014-06-19 14:14:06 -07009#include "GrDitherEffect.h"
10
joshualittb0a8a372014-09-23 09:50:21 -070011#include "gl/GrGLProcessor.h"
krajcevskif461a8f2014-06-19 14:14:06 -070012#include "gl/GrGLSL.h"
joshualittb0a8a372014-09-23 09:50:21 -070013#include "GrTBackendProcessorFactory.h"
krajcevskif461a8f2014-06-19 14:14:06 -070014
15#include "SkRect.h"
16
17//////////////////////////////////////////////////////////////////////////////
18
19class GLDitherEffect;
20
joshualittb0a8a372014-09-23 09:50:21 -070021class DitherEffect : public GrFragmentProcessor {
krajcevskif461a8f2014-06-19 14:14:06 -070022public:
joshualittb0a8a372014-09-23 09:50:21 -070023 static GrFragmentProcessor* Create() {
24 GR_CREATE_STATIC_FRAGMENT_PROCESSOR(gDitherEffect, DitherEffect, ())
bsalomon55fad7a2014-07-08 07:34:20 -070025 return SkRef(gDitherEffect);
krajcevskif461a8f2014-06-19 14:14:06 -070026 }
27
28 virtual ~DitherEffect() {};
29 static const char* Name() { return "Dither"; }
30
joshualittb0a8a372014-09-23 09:50:21 -070031 typedef GLDitherEffect GLProcessor;
krajcevskif461a8f2014-06-19 14:14:06 -070032
joshualittb0a8a372014-09-23 09:50:21 -070033 virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE {
34 return GrTBackendFragmentProcessorFactory<DitherEffect>::getInstance();
krajcevskif461a8f2014-06-19 14:14:06 -070035 }
36
37private:
38 DitherEffect() {
39 this->setWillReadFragmentPosition();
40 }
41
42 // All dither effects are equal
joshualittb0a8a372014-09-23 09:50:21 -070043 virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE { return true; }
krajcevskif461a8f2014-06-19 14:14:06 -070044
egdaniel1a8ecdf2014-10-03 06:24:12 -070045 virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE;
46
joshualittb0a8a372014-09-23 09:50:21 -070047 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
krajcevskif461a8f2014-06-19 14:14:06 -070048
joshualittb0a8a372014-09-23 09:50:21 -070049 typedef GrFragmentProcessor INHERITED;
krajcevskif461a8f2014-06-19 14:14:06 -070050};
51
egdaniel1a8ecdf2014-10-03 06:24:12 -070052void DitherEffect::onComputeInvariantOutput(InvariantOutput* inout) const {
53 inout->fValidFlags = 0;
54 inout->fIsSingleComponent = false;
krajcevskif461a8f2014-06-19 14:14:06 -070055}
56
57//////////////////////////////////////////////////////////////////////////////
58
joshualittb0a8a372014-09-23 09:50:21 -070059GR_DEFINE_FRAGMENT_PROCESSOR_TEST(DitherEffect);
krajcevskif461a8f2014-06-19 14:14:06 -070060
joshualittb0a8a372014-09-23 09:50:21 -070061GrFragmentProcessor* DitherEffect::TestCreate(SkRandom*,
62 GrContext*,
63 const GrDrawTargetCaps&,
64 GrTexture*[]) {
krajcevskif461a8f2014-06-19 14:14:06 -070065 return DitherEffect::Create();
66}
67
68//////////////////////////////////////////////////////////////////////////////
69
joshualittb0a8a372014-09-23 09:50:21 -070070class GLDitherEffect : public GrGLFragmentProcessor {
krajcevskif461a8f2014-06-19 14:14:06 -070071public:
joshualittb0a8a372014-09-23 09:50:21 -070072 GLDitherEffect(const GrBackendProcessorFactory&, const GrProcessor&);
krajcevskif461a8f2014-06-19 14:14:06 -070073
joshualitt15988992014-10-09 15:04:05 -070074 virtual void emitCode(GrGLFPBuilder* builder,
joshualittb0a8a372014-09-23 09:50:21 -070075 const GrFragmentProcessor& fp,
76 const GrProcessorKey& key,
krajcevskif461a8f2014-06-19 14:14:06 -070077 const char* outputColor,
78 const char* inputColor,
79 const TransformedCoordsArray&,
80 const TextureSamplerArray&) SK_OVERRIDE;
81
82private:
joshualittb0a8a372014-09-23 09:50:21 -070083 typedef GrGLFragmentProcessor INHERITED;
krajcevskif461a8f2014-06-19 14:14:06 -070084};
85
joshualittb0a8a372014-09-23 09:50:21 -070086GLDitherEffect::GLDitherEffect(const GrBackendProcessorFactory& factory,
87 const GrProcessor&)
krajcevskif461a8f2014-06-19 14:14:06 -070088 : INHERITED (factory) {
89}
90
joshualitt15988992014-10-09 15:04:05 -070091void GLDitherEffect::emitCode(GrGLFPBuilder* builder,
joshualittb0a8a372014-09-23 09:50:21 -070092 const GrFragmentProcessor& fp,
93 const GrProcessorKey& key,
krajcevskif461a8f2014-06-19 14:14:06 -070094 const char* outputColor,
95 const char* inputColor,
96 const TransformedCoordsArray&,
97 const TextureSamplerArray& samplers) {
joshualitt15988992014-10-09 15:04:05 -070098 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
krajcevskif461a8f2014-06-19 14:14:06 -070099 // Generate a random number based on the fragment position. For this
100 // random number generator, we use the "GLSL rand" function
101 // that seems to be floating around on the internet. It works under
102 // the assumption that sin(<big number>) oscillates with high frequency
103 // and sampling it will generate "randomness". Since we're using this
104 // for rendering and not cryptography it should be OK.
105
106 // For each channel c, add the random offset to the pixel to either bump
107 // it up or let it remain constant during quantization.
joshualitt30ba4362014-08-21 20:18:45 -0700108 fsBuilder->codeAppendf("\t\tfloat r = "
bsalomon22900002014-06-24 11:16:52 -0700109 "fract(sin(dot(%s.xy ,vec2(12.9898,78.233))) * 43758.5453);\n",
joshualitt30ba4362014-08-21 20:18:45 -0700110 fsBuilder->fragmentPosition());
111 fsBuilder->codeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n",
krajcevskif461a8f2014-06-19 14:14:06 -0700112 outputColor, GrGLSLExpr4(inputColor).c_str());
113}
114
115//////////////////////////////////////////////////////////////////////////////
116
joshualittb0a8a372014-09-23 09:50:21 -0700117GrFragmentProcessor* GrDitherEffect::Create() { return DitherEffect::Create(); }