michael@0: /* michael@0: * Copyright 2012 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef GrConvolutionEffect_DEFINED michael@0: #define GrConvolutionEffect_DEFINED michael@0: michael@0: #include "Gr1DKernelEffect.h" michael@0: michael@0: class GrGLConvolutionEffect; michael@0: michael@0: /** michael@0: * A convolution effect. The kernel is specified as an array of 2 * half-width michael@0: * + 1 weights. Each texel is multiplied by it's weight and summed to determine michael@0: * the output color. The output color is modulated by the input color. michael@0: */ michael@0: class GrConvolutionEffect : public Gr1DKernelEffect { michael@0: michael@0: public: michael@0: michael@0: /// Convolve with an arbitrary user-specified kernel michael@0: static GrEffectRef* Create(GrTexture* tex, michael@0: Direction dir, michael@0: int halfWidth, michael@0: const float* kernel, michael@0: bool useBounds, michael@0: float bounds[2]) { michael@0: AutoEffectUnref effect(SkNEW_ARGS(GrConvolutionEffect, (tex, michael@0: dir, michael@0: halfWidth, michael@0: kernel, michael@0: useBounds, michael@0: bounds))); michael@0: return CreateEffectRef(effect); michael@0: } michael@0: michael@0: /// Convolve with a Gaussian kernel michael@0: static GrEffectRef* CreateGaussian(GrTexture* tex, michael@0: Direction dir, michael@0: int halfWidth, michael@0: float gaussianSigma, michael@0: bool useBounds, michael@0: float bounds[2]) { michael@0: AutoEffectUnref effect(SkNEW_ARGS(GrConvolutionEffect, (tex, michael@0: dir, michael@0: halfWidth, michael@0: gaussianSigma, michael@0: useBounds, michael@0: bounds))); michael@0: return CreateEffectRef(effect); michael@0: } michael@0: michael@0: virtual ~GrConvolutionEffect(); michael@0: michael@0: const float* kernel() const { return fKernel; } michael@0: michael@0: const float* bounds() const { return fBounds; } michael@0: bool useBounds() const { return fUseBounds; } michael@0: michael@0: static const char* Name() { return "Convolution"; } michael@0: michael@0: typedef GrGLConvolutionEffect GLEffect; michael@0: michael@0: virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; michael@0: michael@0: virtual void getConstantColorComponents(GrColor*, uint32_t* validFlags) const { michael@0: // If the texture was opaque we could know that the output color if we knew the sum of the michael@0: // kernel values. michael@0: *validFlags = 0; michael@0: } michael@0: michael@0: enum { michael@0: // This was decided based on the min allowed value for the max texture michael@0: // samples per fragment program run in DX9SM2 (32). A sigma param of 4.0 michael@0: // on a blur filter gives a kernel width of 25 while a sigma of 5.0 michael@0: // would exceed a 32 wide kernel. michael@0: kMaxKernelRadius = 12, michael@0: // With a C++11 we could have a constexpr version of WidthFromRadius() michael@0: // and not have to duplicate this calculation. michael@0: kMaxKernelWidth = 2 * kMaxKernelRadius + 1, michael@0: }; michael@0: michael@0: protected: michael@0: michael@0: float fKernel[kMaxKernelWidth]; michael@0: bool fUseBounds; michael@0: float fBounds[2]; michael@0: michael@0: private: michael@0: GrConvolutionEffect(GrTexture*, Direction, michael@0: int halfWidth, michael@0: const float* kernel, michael@0: bool useBounds, michael@0: float bounds[2]); michael@0: michael@0: /// Convolve with a Gaussian kernel michael@0: GrConvolutionEffect(GrTexture*, Direction, michael@0: int halfWidth, michael@0: float gaussianSigma, michael@0: bool useBounds, michael@0: float bounds[2]); michael@0: michael@0: virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; michael@0: michael@0: GR_DECLARE_EFFECT_TEST; michael@0: michael@0: typedef Gr1DKernelEffect INHERITED; michael@0: }; michael@0: michael@0: #endif