1f461a8fdf642ba713dcdfb217534652df1eac278krajcevski/* 2f461a8fdf642ba713dcdfb217534652df1eac278krajcevski * Copyright 2014 Google Inc. 3f461a8fdf642ba713dcdfb217534652df1eac278krajcevski * 4f461a8fdf642ba713dcdfb217534652df1eac278krajcevski * Use of this source code is governed by a BSD-style license that can be 5f461a8fdf642ba713dcdfb217534652df1eac278krajcevski * found in the LICENSE file. 6f461a8fdf642ba713dcdfb217534652df1eac278krajcevski */ 7f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 830ba436f04e61d4505fb854d5fc56079636e0788joshualitt#include "gl/builders/GrGLProgramBuilder.h" 9f461a8fdf642ba713dcdfb217534652df1eac278krajcevski#include "GrDitherEffect.h" 10f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 11b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "gl/GrGLProcessor.h" 12f461a8fdf642ba713dcdfb217534652df1eac278krajcevski#include "gl/GrGLSL.h" 13b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrTBackendProcessorFactory.h" 14f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 15f461a8fdf642ba713dcdfb217534652df1eac278krajcevski#include "SkRect.h" 16f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 17f461a8fdf642ba713dcdfb217534652df1eac278krajcevski////////////////////////////////////////////////////////////////////////////// 18f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 19f461a8fdf642ba713dcdfb217534652df1eac278krajcevskiclass GLDitherEffect; 20f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 21b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass DitherEffect : public GrFragmentProcessor { 22f461a8fdf642ba713dcdfb217534652df1eac278krajcevskipublic: 23b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt static GrFragmentProcessor* Create() { 24b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_CREATE_STATIC_FRAGMENT_PROCESSOR(gDitherEffect, DitherEffect, ()) 2555fad7af61c21d502acb9891d631e8aa29e3628cbsalomon return SkRef(gDitherEffect); 26f461a8fdf642ba713dcdfb217534652df1eac278krajcevski } 27f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 28f461a8fdf642ba713dcdfb217534652df1eac278krajcevski virtual ~DitherEffect() {}; 29f461a8fdf642ba713dcdfb217534652df1eac278krajcevski static const char* Name() { return "Dither"; } 30f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 31b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GLDitherEffect GLProcessor; 32f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 33f461a8fdf642ba713dcdfb217534652df1eac278krajcevski virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; 34f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 35b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE { 36b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return GrTBackendFragmentProcessorFactory<DitherEffect>::getInstance(); 37f461a8fdf642ba713dcdfb217534652df1eac278krajcevski } 38f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 39f461a8fdf642ba713dcdfb217534652df1eac278krajcevskiprivate: 40f461a8fdf642ba713dcdfb217534652df1eac278krajcevski DitherEffect() { 41f461a8fdf642ba713dcdfb217534652df1eac278krajcevski this->setWillReadFragmentPosition(); 42f461a8fdf642ba713dcdfb217534652df1eac278krajcevski } 43f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 44f461a8fdf642ba713dcdfb217534652df1eac278krajcevski // All dither effects are equal 45b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE { return true; } 46f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 47b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 48f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 49b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrFragmentProcessor INHERITED; 50f461a8fdf642ba713dcdfb217534652df1eac278krajcevski}; 51f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 52f461a8fdf642ba713dcdfb217534652df1eac278krajcevskivoid DitherEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { 53f461a8fdf642ba713dcdfb217534652df1eac278krajcevski *validFlags = 0; 54f461a8fdf642ba713dcdfb217534652df1eac278krajcevski} 55f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 56f461a8fdf642ba713dcdfb217534652df1eac278krajcevski////////////////////////////////////////////////////////////////////////////// 57f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 58b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(DitherEffect); 59f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 60b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* DitherEffect::TestCreate(SkRandom*, 61b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrContext*, 62b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrDrawTargetCaps&, 63b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrTexture*[]) { 64f461a8fdf642ba713dcdfb217534652df1eac278krajcevski return DitherEffect::Create(); 65f461a8fdf642ba713dcdfb217534652df1eac278krajcevski} 66f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 67f461a8fdf642ba713dcdfb217534652df1eac278krajcevski////////////////////////////////////////////////////////////////////////////// 68f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 69b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GLDitherEffect : public GrGLFragmentProcessor { 70f461a8fdf642ba713dcdfb217534652df1eac278krajcevskipublic: 71b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GLDitherEffect(const GrBackendProcessorFactory&, const GrProcessor&); 72f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 7330ba436f04e61d4505fb854d5fc56079636e0788joshualitt virtual void emitCode(GrGLProgramBuilder* builder, 74b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrFragmentProcessor& fp, 75b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessorKey& key, 76f461a8fdf642ba713dcdfb217534652df1eac278krajcevski const char* outputColor, 77f461a8fdf642ba713dcdfb217534652df1eac278krajcevski const char* inputColor, 78f461a8fdf642ba713dcdfb217534652df1eac278krajcevski const TransformedCoordsArray&, 79f461a8fdf642ba713dcdfb217534652df1eac278krajcevski const TextureSamplerArray&) SK_OVERRIDE; 80f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 81f461a8fdf642ba713dcdfb217534652df1eac278krajcevskiprivate: 82b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt typedef GrGLFragmentProcessor INHERITED; 83f461a8fdf642ba713dcdfb217534652df1eac278krajcevski}; 84f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 85b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGLDitherEffect::GLDitherEffect(const GrBackendProcessorFactory& factory, 86b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessor&) 87f461a8fdf642ba713dcdfb217534652df1eac278krajcevski : INHERITED (factory) { 88f461a8fdf642ba713dcdfb217534652df1eac278krajcevski} 89f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 9030ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GLDitherEffect::emitCode(GrGLProgramBuilder* builder, 91b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrFragmentProcessor& fp, 92b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt const GrProcessorKey& key, 93f461a8fdf642ba713dcdfb217534652df1eac278krajcevski const char* outputColor, 94f461a8fdf642ba713dcdfb217534652df1eac278krajcevski const char* inputColor, 95f461a8fdf642ba713dcdfb217534652df1eac278krajcevski const TransformedCoordsArray&, 96f461a8fdf642ba713dcdfb217534652df1eac278krajcevski const TextureSamplerArray& samplers) { 9730ba436f04e61d4505fb854d5fc56079636e0788joshualitt GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 98f461a8fdf642ba713dcdfb217534652df1eac278krajcevski // Generate a random number based on the fragment position. For this 99f461a8fdf642ba713dcdfb217534652df1eac278krajcevski // random number generator, we use the "GLSL rand" function 100f461a8fdf642ba713dcdfb217534652df1eac278krajcevski // that seems to be floating around on the internet. It works under 101f461a8fdf642ba713dcdfb217534652df1eac278krajcevski // the assumption that sin(<big number>) oscillates with high frequency 102f461a8fdf642ba713dcdfb217534652df1eac278krajcevski // and sampling it will generate "randomness". Since we're using this 103f461a8fdf642ba713dcdfb217534652df1eac278krajcevski // for rendering and not cryptography it should be OK. 104f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 105f461a8fdf642ba713dcdfb217534652df1eac278krajcevski // For each channel c, add the random offset to the pixel to either bump 106f461a8fdf642ba713dcdfb217534652df1eac278krajcevski // it up or let it remain constant during quantization. 10730ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\t\tfloat r = " 10822900008fb89afe4687a40db8737553ee0e55621bsalomon "fract(sin(dot(%s.xy ,vec2(12.9898,78.233))) * 43758.5453);\n", 10930ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->fragmentPosition()); 11030ba436f04e61d4505fb854d5fc56079636e0788joshualitt fsBuilder->codeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n", 111f461a8fdf642ba713dcdfb217534652df1eac278krajcevski outputColor, GrGLSLExpr4(inputColor).c_str()); 112f461a8fdf642ba713dcdfb217534652df1eac278krajcevski} 113f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 114f461a8fdf642ba713dcdfb217534652df1eac278krajcevski////////////////////////////////////////////////////////////////////////////// 115f461a8fdf642ba713dcdfb217534652df1eac278krajcevski 116b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* GrDitherEffect::Create() { return DitherEffect::Create(); } 117