1 2 /* 3 * Copyright 2010 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 11 #ifndef GrSamplerState_DEFINED 12 #define GrSamplerState_DEFINED 13 14 #include "GrTypes.h" 15 #include "GrMatrix.h" 16 17 #define MAX_KERNEL_WIDTH 25 18 19 class GrSamplerState { 20 public: 21 enum Filter { 22 /** 23 * Read the closest src texel to the sample position 24 */ 25 kNearest_Filter, 26 /** 27 * Blend between closest 4 src texels to sample position (tent filter) 28 */ 29 kBilinear_Filter, 30 /** 31 * Average of 4 bilinear filterings spaced +/- 1 texel from sample 32 * position in x and y. Intended for averaging 16 texels in a downsample 33 * pass. (rasterizing such that texture samples fall exactly halfway 34 * between texels in x and y spaced 4 texels apart.) Only supported 35 * on shader backends. 36 */ 37 k4x4Downsample_Filter, 38 /** 39 * Apply a separable convolution kernel. 40 */ 41 kConvolution_Filter, 42 /** 43 * Apply a dilate filter (max over a 1D radius). 44 */ 45 kDilate_Filter, 46 /** 47 * Apply an erode filter (min over a 1D radius). 48 */ 49 kErode_Filter, 50 51 kDefault_Filter = kNearest_Filter 52 }; 53 54 /** 55 * The intepretation of the texture matrix depends on the sample mode. The 56 * texture matrix is applied both when the texture coordinates are explicit 57 * and when vertex positions are used as texture coordinates. In the latter 58 * case the texture matrix is applied to the pre-view-matrix position 59 * values. 60 * 61 * kNormal_SampleMode 62 * The post-matrix texture coordinates are in normalize space with (0,0) at 63 * the top-left and (1,1) at the bottom right. 64 * kRadial_SampleMode 65 * The matrix specifies the radial gradient parameters. 66 * (0,0) in the post-matrix space is center of the radial gradient. 67 * kRadial2_SampleMode 68 * Matrix transforms to space where first circle is centered at the 69 * origin. The second circle will be centered (x, 0) where x may be 70 * 0 and is provided by setRadial2Params. The post-matrix space is 71 * normalized such that 1 is the second radius - first radius. 72 * kSweepSampleMode 73 * The angle from the origin of texture coordinates in post-matrix space 74 * determines the gradient value. 75 */ 76 enum SampleMode { 77 kNormal_SampleMode, //!< sample color directly 78 kRadial_SampleMode, //!< treat as radial gradient 79 kRadial2_SampleMode, //!< treat as 2-point radial gradient 80 kSweep_SampleMode, //!< treat as sweep gradient 81 82 kDefault_SampleMode = kNormal_SampleMode 83 }; 84 85 /** 86 * Describes how a texture is sampled when coordinates are outside the 87 * texture border 88 */ 89 enum WrapMode { 90 kClamp_WrapMode, 91 kRepeat_WrapMode, 92 kMirror_WrapMode, 93 94 kDefault_WrapMode = kClamp_WrapMode 95 }; 96 97 /** 98 * For the filters which perform more than one texture sample (convolution, 99 * erode, dilate), this determines the direction in which the texture 100 * coordinates will be incremented. 101 */ 102 enum FilterDirection { 103 kX_FilterDirection, 104 kY_FilterDirection, 105 106 kDefault_FilterDirection = kX_FilterDirection, 107 }; 108 /** 109 * Default sampler state is set to clamp, use normal sampling mode, be 110 * unfiltered, and use identity matrix. 111 */ GrSamplerState()112 GrSamplerState() 113 : fRadial2CenterX1() 114 , fRadial2Radius0() 115 , fRadial2PosRoot() { 116 this->reset(); 117 } 118 getWrapX()119 WrapMode getWrapX() const { return fWrapX; } getWrapY()120 WrapMode getWrapY() const { return fWrapY; } getFilterDirection()121 FilterDirection getFilterDirection() const { return fFilterDirection; } getSampleMode()122 SampleMode getSampleMode() const { return fSampleMode; } getMatrix()123 const GrMatrix& getMatrix() const { return fMatrix; } getTextureDomain()124 const GrRect& getTextureDomain() const { return fTextureDomain; } hasTextureDomain()125 bool hasTextureDomain() const {return SkIntToScalar(0) != fTextureDomain.right();} getFilter()126 Filter getFilter() const { return fFilter; } getKernelWidth()127 int getKernelWidth() const { return fKernelWidth; } getKernel()128 const float* getKernel() const { return fKernel; } swapsRAndB()129 bool swapsRAndB() const { return fSwapRAndB; } 130 isGradient()131 bool isGradient() const { 132 return kRadial_SampleMode == fSampleMode || 133 kRadial2_SampleMode == fSampleMode || 134 kSweep_SampleMode == fSampleMode; 135 } 136 setWrapX(WrapMode mode)137 void setWrapX(WrapMode mode) { fWrapX = mode; } setWrapY(WrapMode mode)138 void setWrapY(WrapMode mode) { fWrapY = mode; } setSampleMode(SampleMode mode)139 void setSampleMode(SampleMode mode) { fSampleMode = mode; } setFilterDirection(FilterDirection mode)140 void setFilterDirection(FilterDirection mode) { fFilterDirection = mode; } 141 142 /** 143 * Access the sampler's matrix. See SampleMode for explanation of 144 * relationship between the matrix and sample mode. 145 */ matrix()146 GrMatrix* matrix() { return &fMatrix; } 147 148 /** 149 * Sets the sampler's texture coordinate domain to a 150 * custom rectangle, rather than the default (0,1). 151 * This option is currently only supported with kClamp_WrapMode 152 */ setTextureDomain(const GrRect & textureDomain)153 void setTextureDomain(const GrRect& textureDomain) { fTextureDomain = textureDomain; } 154 155 /** 156 * Swaps the R and B components when reading from the texture. Has no effect 157 * if the texture is alpha only. 158 */ setRAndBSwap(bool swap)159 void setRAndBSwap(bool swap) { fSwapRAndB = swap; } 160 161 /** 162 * Multiplies the current sampler matrix a matrix 163 * 164 * After this call M' = M*m where M is the old matrix, m is the parameter 165 * to this function, and M' is the new matrix. (We consider points to 166 * be column vectors so tex cood vector t is transformed by matrix X as 167 * t' = X*t.) 168 * 169 * @param matrix the matrix used to modify the matrix. 170 */ preConcatMatrix(const GrMatrix & matrix)171 void preConcatMatrix(const GrMatrix& matrix) { fMatrix.preConcat(matrix); } 172 173 /** 174 * Sets filtering type. 175 * @param filter type of filtering to apply 176 */ setFilter(Filter filter)177 void setFilter(Filter filter) { fFilter = filter; } 178 reset(WrapMode wrapXAndY,Filter filter,FilterDirection direction,const GrMatrix & matrix)179 void reset(WrapMode wrapXAndY, 180 Filter filter, 181 FilterDirection direction, 182 const GrMatrix& matrix) { 183 fWrapX = wrapXAndY; 184 fWrapY = wrapXAndY; 185 fSampleMode = kDefault_SampleMode; 186 fFilter = filter; 187 fFilterDirection = direction; 188 fMatrix = matrix; 189 fTextureDomain.setEmpty(); 190 fSwapRAndB = false; 191 } reset(WrapMode wrapXAndY,Filter filter,const GrMatrix & matrix)192 void reset(WrapMode wrapXAndY, Filter filter, const GrMatrix& matrix) { 193 this->reset(wrapXAndY, filter, kDefault_FilterDirection, matrix); 194 } reset(WrapMode wrapXAndY,Filter filter)195 void reset(WrapMode wrapXAndY, 196 Filter filter) { 197 this->reset(wrapXAndY, filter, kDefault_FilterDirection, GrMatrix::I()); 198 } reset(const GrMatrix & matrix)199 void reset(const GrMatrix& matrix) { 200 this->reset(kDefault_WrapMode, kDefault_Filter, kDefault_FilterDirection, matrix); 201 } reset()202 void reset() { 203 this->reset(kDefault_WrapMode, kDefault_Filter, kDefault_FilterDirection, GrMatrix::I()); 204 } 205 getRadial2CenterX1()206 GrScalar getRadial2CenterX1() const { return fRadial2CenterX1; } getRadial2Radius0()207 GrScalar getRadial2Radius0() const { return fRadial2Radius0; } isRadial2PosRoot()208 bool isRadial2PosRoot() const { return SkToBool(fRadial2PosRoot); } 209 // do the radial gradient params lead to a linear (rather than quadratic) 210 // equation. radial2IsDegenerate()211 bool radial2IsDegenerate() const { return GR_Scalar1 == fRadial2CenterX1; } 212 213 /** 214 * Sets the parameters for kRadial2_SampleMode. The texture 215 * matrix must be set so that the first point is at (0,0) and the second 216 * point lies on the x-axis. The second radius minus the first is 1 unit. 217 * The additional parameters to define the gradient are specified by this 218 * function. 219 */ setRadial2Params(GrScalar centerX1,GrScalar radius0,bool posRoot)220 void setRadial2Params(GrScalar centerX1, GrScalar radius0, bool posRoot) { 221 fRadial2CenterX1 = centerX1; 222 fRadial2Radius0 = radius0; 223 fRadial2PosRoot = posRoot; 224 } 225 setConvolutionParams(int kernelWidth,const float * kernel)226 void setConvolutionParams(int kernelWidth, const float* kernel) { 227 GrAssert(kernelWidth >= 0 && kernelWidth <= MAX_KERNEL_WIDTH); 228 fKernelWidth = kernelWidth; 229 if (NULL != kernel) { 230 memcpy(fKernel, kernel, kernelWidth * sizeof(float)); 231 } 232 } 233 setMorphologyRadius(int radius)234 void setMorphologyRadius(int radius) { 235 GrAssert(radius >= 0 && radius <= MAX_KERNEL_WIDTH); 236 fKernelWidth = radius; 237 } 238 239 private: 240 WrapMode fWrapX : 8; 241 WrapMode fWrapY : 8; 242 FilterDirection fFilterDirection : 8; 243 SampleMode fSampleMode : 8; 244 Filter fFilter : 8; 245 GrMatrix fMatrix; 246 bool fSwapRAndB; 247 GrRect fTextureDomain; 248 249 // these are undefined unless fSampleMode == kRadial2_SampleMode 250 GrScalar fRadial2CenterX1; 251 GrScalar fRadial2Radius0; 252 SkBool8 fRadial2PosRoot; 253 254 // These are undefined unless fFilter == kConvolution_Filter 255 uint8_t fKernelWidth; 256 float fKernel[MAX_KERNEL_WIDTH]; 257 }; 258 259 #endif 260 261