blob: 324472c9720bb3d7992a07b7297dbd81b6567704 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comac10a2d2010-12-22 21:39:39 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * 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.
reed@google.comac10a2d2010-12-22 21:39:39 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
reed@google.comac10a2d2010-12-22 21:39:39 +000011#ifndef GrSamplerState_DEFINED
12#define GrSamplerState_DEFINED
13
14#include "GrTypes.h"
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000015#include "GrMatrix.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000016
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +000017#define MAX_KERNEL_WIDTH 25
18
reed@google.comac10a2d2010-12-22 21:39:39 +000019class GrSamplerState {
20public:
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +000021 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
bsalomon@google.com1f221a72011-08-23 20:54:07 +000034 * between texels in x and y spaced 4 texels apart.) Only supported
35 * on shader backends.
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +000036 */
37 k4x4Downsample_Filter,
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +000038 /**
39 * Apply a separable convolution kernel.
40 */
41 kConvolution_Filter
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +000042 };
43
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000044 /**
45 * The intepretation of the texture matrix depends on the sample mode. The
46 * texture matrix is applied both when the texture coordinates are explicit
47 * and when vertex positions are used as texture coordinates. In the latter
48 * case the texture matrix is applied to the pre-view-matrix position
49 * values.
50 *
51 * kNormal_SampleMode
52 * The post-matrix texture coordinates are in normalize space with (0,0) at
53 * the top-left and (1,1) at the bottom right.
54 * kRadial_SampleMode
55 * The matrix specifies the radial gradient parameters.
56 * (0,0) in the post-matrix space is center of the radial gradient.
57 * kRadial2_SampleMode
58 * Matrix transforms to space where first circle is centered at the
59 * origin. The second circle will be centered (x, 0) where x may be
60 * 0 and is provided by setRadial2Params. The post-matrix space is
61 * normalized such that 1 is the second radius - first radius.
62 * kSweepSampleMode
63 * The angle from the origin of texture coordinates in post-matrix space
64 * determines the gradient value.
65 */
reed@google.comac10a2d2010-12-22 21:39:39 +000066 enum SampleMode {
67 kNormal_SampleMode, //!< sample color directly
reed@google.comac10a2d2010-12-22 21:39:39 +000068 kRadial_SampleMode, //!< treat as radial gradient
69 kRadial2_SampleMode, //!< treat as 2-point radial gradient
70 kSweep_SampleMode, //!< treat as sweep gradient
71 };
72
73 /**
74 * Describes how a texture is sampled when coordinates are outside the
75 * texture border
76 */
77 enum WrapMode {
78 kClamp_WrapMode,
79 kRepeat_WrapMode,
80 kMirror_WrapMode
81 };
82
83 /**
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000084 * Default sampler state is set to clamp, use normal sampling mode, be
85 * unfiltered, and use identity matrix.
reed@google.comac10a2d2010-12-22 21:39:39 +000086 */
bsalomon@google.com6aab8e32011-06-21 20:32:12 +000087 GrSamplerState()
88 : fRadial2CenterX1()
89 , fRadial2Radius0()
90 , fRadial2PosRoot() {
reed@google.comac10a2d2010-12-22 21:39:39 +000091 this->setClampNoFilter();
92 }
93
bsalomon@google.com6aab8e32011-06-21 20:32:12 +000094 explicit GrSamplerState(Filter filter)
95 : fRadial2CenterX1()
96 , fRadial2Radius0()
97 , fRadial2PosRoot() {
reed@google.comac10a2d2010-12-22 21:39:39 +000098 fWrapX = kClamp_WrapMode;
99 fWrapY = kClamp_WrapMode;
100 fSampleMode = kNormal_SampleMode;
101 fFilter = filter;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000102 fMatrix.setIdentity();
junov@google.com6acc9b32011-05-16 18:32:07 +0000103 fTextureDomain.setEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000104 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000105
bsalomon@google.com6aab8e32011-06-21 20:32:12 +0000106 GrSamplerState(WrapMode wx, WrapMode wy, Filter filter)
107 : fRadial2CenterX1()
108 , fRadial2Radius0()
109 , fRadial2PosRoot() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000110 fWrapX = wx;
111 fWrapY = wy;
112 fSampleMode = kNormal_SampleMode;
113 fFilter = filter;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000114 fMatrix.setIdentity();
junov@google.com6acc9b32011-05-16 18:32:07 +0000115 fTextureDomain.setEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000116 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000117
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000118 GrSamplerState(WrapMode wx, WrapMode wy,
bsalomon@google.com6aab8e32011-06-21 20:32:12 +0000119 const GrMatrix& matrix, Filter filter)
120 : fRadial2CenterX1()
121 , fRadial2Radius0()
122 , fRadial2PosRoot() {
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000123 fWrapX = wx;
124 fWrapY = wy;
125 fSampleMode = kNormal_SampleMode;
126 fFilter = filter;
127 fMatrix = matrix;
junov@google.com6acc9b32011-05-16 18:32:07 +0000128 fTextureDomain.setEmpty();
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000129 }
130
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000131 GrSamplerState(WrapMode wx, WrapMode wy, SampleMode sample,
bsalomon@google.com6aab8e32011-06-21 20:32:12 +0000132 const GrMatrix& matrix, Filter filter)
133 : fRadial2CenterX1()
134 , fRadial2Radius0()
135 , fRadial2PosRoot() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000136 fWrapX = wx;
137 fWrapY = wy;
138 fSampleMode = sample;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000139 fMatrix = matrix;
reed@google.comac10a2d2010-12-22 21:39:39 +0000140 fFilter = filter;
junov@google.com6acc9b32011-05-16 18:32:07 +0000141 fTextureDomain.setEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000142 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000143
reed@google.comac10a2d2010-12-22 21:39:39 +0000144 WrapMode getWrapX() const { return fWrapX; }
145 WrapMode getWrapY() const { return fWrapY; }
146 SampleMode getSampleMode() const { return fSampleMode; }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000147 const GrMatrix& getMatrix() const { return fMatrix; }
junov@google.com6acc9b32011-05-16 18:32:07 +0000148 const GrRect& getTextureDomain() const { return fTextureDomain; }
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000149 bool hasTextureDomain() const {return SkIntToScalar(0) != fTextureDomain.right();}
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000150 Filter getFilter() const { return fFilter; }
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000151 int getKernelWidth() const { return fKernelWidth; }
152 const float* getKernel() const { return fKernel; }
153 const float* getImageIncrement() const { return fImageIncrement; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000154
155 bool isGradient() const {
156 return kRadial_SampleMode == fSampleMode ||
157 kRadial2_SampleMode == fSampleMode ||
158 kSweep_SampleMode == fSampleMode;
159 }
160
161 void setWrapX(WrapMode mode) { fWrapX = mode; }
162 void setWrapY(WrapMode mode) { fWrapY = mode; }
163 void setSampleMode(SampleMode mode) { fSampleMode = mode; }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000164
165 /**
166 * Sets the sampler's matrix. See SampleMode for explanation of
167 * relationship between the matrix and sample mode.
168 * @param matrix the matrix to set
169 */
170 void setMatrix(const GrMatrix& matrix) { fMatrix = matrix; }
171
172 /**
junov@google.com6acc9b32011-05-16 18:32:07 +0000173 * Sets the sampler's texture coordinate domain to a
174 * custom rectangle, rather than the default (0,1).
175 * This option is currently only supported with kClamp_WrapMode
176 */
177 void setTextureDomain(const GrRect& textureDomain) { fTextureDomain = textureDomain; }
178
179 /**
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000180 * Multiplies the current sampler matrix a matrix
181 *
182 * After this call M' = M*m where M is the old matrix, m is the parameter
183 * to this function, and M' is the new matrix. (We consider points to
184 * be column vectors so tex cood vector t is transformed by matrix X as
185 * t' = X*t.)
186 *
187 * @param matrix the matrix used to modify the matrix.
188 */
189 void preConcatMatrix(const GrMatrix& matrix) { fMatrix.preConcat(matrix); }
190
191 /**
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000192 * Sets filtering type.
193 * @param filter type of filtering to apply
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000194 */
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000195 void setFilter(Filter filter) { fFilter = filter; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000196
197 void setClampNoFilter() {
198 fWrapX = kClamp_WrapMode;
199 fWrapY = kClamp_WrapMode;
200 fSampleMode = kNormal_SampleMode;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000201 fFilter = kNearest_Filter;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000202 fMatrix.setIdentity();
junov@google.com6acc9b32011-05-16 18:32:07 +0000203 fTextureDomain.setEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000204 }
205
206 GrScalar getRadial2CenterX1() const { return fRadial2CenterX1; }
207 GrScalar getRadial2Radius0() const { return fRadial2Radius0; }
208 bool isRadial2PosRoot() const { return fRadial2PosRoot; }
bsalomon@google.com22c5dea2011-07-07 14:38:03 +0000209 // do the radial gradient params lead to a linear (rather than quadratic)
210 // equation.
211 bool radial2IsDegenerate() const { return GR_Scalar1 == fRadial2CenterX1; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000212
213 /**
bsalomon@google.com5782d712011-01-21 21:03:59 +0000214 * 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
reed@google.comac10a2d2010-12-22 21:39:39 +0000216 * 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 */
220 void setRadial2Params(GrScalar centerX1, GrScalar radius0, bool posRoot) {
221 fRadial2CenterX1 = centerX1;
222 fRadial2Radius0 = radius0;
223 fRadial2PosRoot = posRoot;
224 }
225
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000226 void setConvolutionParams(int kernelWidth, const float* kernel, float imageIncrement[2]) {
227 GrAssert(kernelWidth >= 0 && kernelWidth <= MAX_KERNEL_WIDTH);
228 fKernelWidth = kernelWidth;
229 if (NULL != kernel) {
230 memcpy(fKernel, kernel, kernelWidth * sizeof(float));
231 }
232 if (NULL != imageIncrement) {
233 memcpy(fImageIncrement, imageIncrement, sizeof(fImageIncrement));
234 } else {
235 memset(fImageIncrement, 0, sizeof(fImageIncrement));
236 }
237 }
238
reed@google.comac10a2d2010-12-22 21:39:39 +0000239 static const GrSamplerState& ClampNoFilter() {
240 return gClampNoFilter;
241 }
242
243private:
244 WrapMode fWrapX;
245 WrapMode fWrapY;
246 SampleMode fSampleMode;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000247 Filter fFilter;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000248 GrMatrix fMatrix;
junov@google.com6acc9b32011-05-16 18:32:07 +0000249 GrRect fTextureDomain;
reed@google.comac10a2d2010-12-22 21:39:39 +0000250
251 // these are undefined unless fSampleMode == kRadial2_SampleMode
252 GrScalar fRadial2CenterX1;
253 GrScalar fRadial2Radius0;
254 bool fRadial2PosRoot;
255
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000256 // These are undefined unless fFilter == kConvolution_Filter
257 int fKernelWidth;
258 float fKernel[MAX_KERNEL_WIDTH];
259 float fImageIncrement[2];
260
reed@google.comac10a2d2010-12-22 21:39:39 +0000261 static const GrSamplerState gClampNoFilter;
262};
263
264#endif
265