2 * Copyright 2014 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "gl/builders/GrGLProgramBuilder.h"
9 #include "GrDitherEffect.h"
11 #include "gl/GrGLProcessor.h"
12 #include "gl/GrGLSL.h"
13 #include "GrTBackendProcessorFactory.h"
17 //////////////////////////////////////////////////////////////////////////////
21 class DitherEffect : public GrFragmentProcessor {
23 static GrFragmentProcessor* Create() {
24 GR_CREATE_STATIC_PROCESSOR(gDitherEffect, DitherEffect, ())
25 return SkRef(gDitherEffect);
28 virtual ~DitherEffect() {};
29 static const char* Name() { return "Dither"; }
31 typedef GLDitherEffect GLProcessor;
33 virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE {
34 return GrTBackendFragmentProcessorFactory<DitherEffect>::getInstance();
39 this->setWillReadFragmentPosition();
42 // All dither effects are equal
43 virtual bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE { return true; }
45 virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE;
47 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
49 typedef GrFragmentProcessor INHERITED;
52 void DitherEffect::onComputeInvariantOutput(InvariantOutput* inout) const {
53 inout->setToUnknown(InvariantOutput::kWill_ReadInput);
56 //////////////////////////////////////////////////////////////////////////////
58 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(DitherEffect);
60 GrFragmentProcessor* DitherEffect::TestCreate(SkRandom*,
62 const GrDrawTargetCaps&,
64 return DitherEffect::Create();
67 //////////////////////////////////////////////////////////////////////////////
69 class GLDitherEffect : public GrGLFragmentProcessor {
71 GLDitherEffect(const GrBackendProcessorFactory&, const GrProcessor&);
73 virtual void emitCode(GrGLFPBuilder* builder,
74 const GrFragmentProcessor& fp,
75 const GrProcessorKey& key,
76 const char* outputColor,
77 const char* inputColor,
78 const TransformedCoordsArray&,
79 const TextureSamplerArray&) SK_OVERRIDE;
82 typedef GrGLFragmentProcessor INHERITED;
85 GLDitherEffect::GLDitherEffect(const GrBackendProcessorFactory& factory,
87 : INHERITED (factory) {
90 void GLDitherEffect::emitCode(GrGLFPBuilder* builder,
91 const GrFragmentProcessor& fp,
92 const GrProcessorKey& key,
93 const char* outputColor,
94 const char* inputColor,
95 const TransformedCoordsArray&,
96 const TextureSamplerArray& samplers) {
97 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
98 // Generate a random number based on the fragment position. For this
99 // random number generator, we use the "GLSL rand" function
100 // that seems to be floating around on the internet. It works under
101 // the assumption that sin(<big number>) oscillates with high frequency
102 // and sampling it will generate "randomness". Since we're using this
103 // for rendering and not cryptography it should be OK.
105 // For each channel c, add the random offset to the pixel to either bump
106 // it up or let it remain constant during quantization.
107 fsBuilder->codeAppendf("\t\tfloat r = "
108 "fract(sin(dot(%s.xy ,vec2(12.9898,78.233))) * 43758.5453);\n",
109 fsBuilder->fragmentPosition());
110 fsBuilder->codeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n",
111 outputColor, GrGLSLExpr4(inputColor).c_str());
114 //////////////////////////////////////////////////////////////////////////////
116 GrFragmentProcessor* GrDitherEffect::Create() { return DitherEffect::Create(); }