180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2012 Google Inc. 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifndef GrConvolutionEffect_DEFINED 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define GrConvolutionEffect_DEFINED 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "Gr1DKernelEffect.h" 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass GrGLConvolutionEffect; 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * A convolution effect. The kernel is specified as an array of 2 * half-width 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * + 1 weights. Each texel is multiplied by it's weight and summed to determine 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * the output color. The output color is modulated by the input color. 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass GrConvolutionEffect : public Gr1DKernelEffect { 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic: 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /// Convolve with an arbitrary user-specified kernel 2558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger static GrEffectRef* Create(GrTexture* tex, 2658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger Direction dir, 2758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger int halfWidth, 2858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const float* kernel, 29e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger bool useBounds, 30e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger float bounds[2]) { 31d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger AutoEffectUnref effect(SkNEW_ARGS(GrConvolutionEffect, (tex, 32d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger dir, 33d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger halfWidth, 3458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger kernel, 35e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger useBounds, 36e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger bounds))); 37d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return CreateEffectRef(effect); 38d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger } 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 40363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger /// Convolve with a Gaussian kernel 41d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger static GrEffectRef* CreateGaussian(GrTexture* tex, 42d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger Direction dir, 43d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger int halfWidth, 4458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger float gaussianSigma, 45e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger bool useBounds, 46e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger float bounds[2]) { 47d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger AutoEffectUnref effect(SkNEW_ARGS(GrConvolutionEffect, (tex, 48d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger dir, 49d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger halfWidth, 5058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger gaussianSigma, 51e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger useBounds, 52e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger bounds))); 53d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return CreateEffectRef(effect); 54d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger } 55d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru virtual ~GrConvolutionEffect(); 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const float* kernel() const { return fKernel; } 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 60e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger const float* bounds() const { return fBounds; } 61e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger bool useBounds() const { return fUseBounds; } 6258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static const char* Name() { return "Convolution"; } 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 65363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger typedef GrGLConvolutionEffect GLEffect; 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 67363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; 68d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 69096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger virtual void getConstantColorComponents(GrColor*, uint32_t* validFlags) const { 70d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger // If the texture was opaque we could know that the output color if we knew the sum of the 71d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger // kernel values. 72d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger *validFlags = 0; 73d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger } 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru enum { 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // This was decided based on the min allowed value for the max texture 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // samples per fragment program run in DX9SM2 (32). A sigma param of 4.0 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // on a blur filter gives a kernel width of 25 while a sigma of 5.0 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // would exceed a 32 wide kernel. 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kMaxKernelRadius = 12, 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // With a C++11 we could have a constexpr version of WidthFromRadius() 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // and not have to duplicate this calculation. 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru kMaxKernelWidth = 2 * kMaxKernelRadius + 1, 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru }; 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprotected: 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru float fKernel[kMaxKernelWidth]; 89e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger bool fUseBounds; 90e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger float fBounds[2]; 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate: 93d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger GrConvolutionEffect(GrTexture*, Direction, 9458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger int halfWidth, 9558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const float* kernel, 96e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger bool useBounds, 97e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger float bounds[2]); 98d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 99d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger /// Convolve with a Gaussian kernel 100d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger GrConvolutionEffect(GrTexture*, Direction, 101d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger int halfWidth, 10258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger float gaussianSigma, 103e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger bool useBounds, 104e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger float bounds[2]); 105d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 106d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; 107d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 108363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger GR_DECLARE_EFFECT_TEST; 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru typedef Gr1DKernelEffect INHERITED; 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 114