blob: 9c217dbf9c9bbb9771cb668aca28be2e50fdcfeb [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();
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000115 fSwapRAndB = false;
junov@google.com6acc9b32011-05-16 18:32:07 +0000116 fTextureDomain.setEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000117 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000118
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000119 GrSamplerState(WrapMode wx, WrapMode wy,
bsalomon@google.com6aab8e32011-06-21 20:32:12 +0000120 const GrMatrix& matrix, Filter filter)
121 : fRadial2CenterX1()
122 , fRadial2Radius0()
123 , fRadial2PosRoot() {
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000124 fWrapX = wx;
125 fWrapY = wy;
126 fSampleMode = kNormal_SampleMode;
127 fFilter = filter;
128 fMatrix = matrix;
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000129 fSwapRAndB = false;
junov@google.com6acc9b32011-05-16 18:32:07 +0000130 fTextureDomain.setEmpty();
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000131 }
132
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000133 GrSamplerState(WrapMode wx, WrapMode wy, SampleMode sample,
bsalomon@google.com6aab8e32011-06-21 20:32:12 +0000134 const GrMatrix& matrix, Filter filter)
135 : fRadial2CenterX1()
136 , fRadial2Radius0()
137 , fRadial2PosRoot() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000138 fWrapX = wx;
139 fWrapY = wy;
140 fSampleMode = sample;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000141 fMatrix = matrix;
reed@google.comac10a2d2010-12-22 21:39:39 +0000142 fFilter = filter;
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000143 fSwapRAndB = false;
junov@google.com6acc9b32011-05-16 18:32:07 +0000144 fTextureDomain.setEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000145 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000146
reed@google.comac10a2d2010-12-22 21:39:39 +0000147 WrapMode getWrapX() const { return fWrapX; }
148 WrapMode getWrapY() const { return fWrapY; }
149 SampleMode getSampleMode() const { return fSampleMode; }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000150 const GrMatrix& getMatrix() const { return fMatrix; }
junov@google.com6acc9b32011-05-16 18:32:07 +0000151 const GrRect& getTextureDomain() const { return fTextureDomain; }
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000152 bool hasTextureDomain() const {return SkIntToScalar(0) != fTextureDomain.right();}
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000153 Filter getFilter() const { return fFilter; }
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000154 int getKernelWidth() const { return fKernelWidth; }
155 const float* getKernel() const { return fKernel; }
156 const float* getImageIncrement() const { return fImageIncrement; }
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000157 bool swapsRAndB() const { return fSwapRAndB; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000158
159 bool isGradient() const {
160 return kRadial_SampleMode == fSampleMode ||
161 kRadial2_SampleMode == fSampleMode ||
162 kSweep_SampleMode == fSampleMode;
163 }
164
165 void setWrapX(WrapMode mode) { fWrapX = mode; }
166 void setWrapY(WrapMode mode) { fWrapY = mode; }
167 void setSampleMode(SampleMode mode) { fSampleMode = mode; }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000168
169 /**
170 * Sets the sampler's matrix. See SampleMode for explanation of
171 * relationship between the matrix and sample mode.
172 * @param matrix the matrix to set
173 */
174 void setMatrix(const GrMatrix& matrix) { fMatrix = matrix; }
175
176 /**
junov@google.com6acc9b32011-05-16 18:32:07 +0000177 * Sets the sampler's texture coordinate domain to a
178 * custom rectangle, rather than the default (0,1).
179 * This option is currently only supported with kClamp_WrapMode
180 */
181 void setTextureDomain(const GrRect& textureDomain) { fTextureDomain = textureDomain; }
182
183 /**
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000184 * Swaps the R and B components when reading from the texture. Has no effect
185 * if the texture is alpha only.
186 */
187 void setRAndBSwap(bool swap) { fSwapRAndB = swap; }
188
189 /**
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000190 * Multiplies the current sampler matrix a matrix
191 *
192 * After this call M' = M*m where M is the old matrix, m is the parameter
193 * to this function, and M' is the new matrix. (We consider points to
194 * be column vectors so tex cood vector t is transformed by matrix X as
195 * t' = X*t.)
196 *
197 * @param matrix the matrix used to modify the matrix.
198 */
199 void preConcatMatrix(const GrMatrix& matrix) { fMatrix.preConcat(matrix); }
200
201 /**
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000202 * Sets filtering type.
203 * @param filter type of filtering to apply
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000204 */
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000205 void setFilter(Filter filter) { fFilter = filter; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000206
207 void setClampNoFilter() {
208 fWrapX = kClamp_WrapMode;
209 fWrapY = kClamp_WrapMode;
210 fSampleMode = kNormal_SampleMode;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000211 fFilter = kNearest_Filter;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000212 fMatrix.setIdentity();
junov@google.com6acc9b32011-05-16 18:32:07 +0000213 fTextureDomain.setEmpty();
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000214 fSwapRAndB = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000215 }
216
217 GrScalar getRadial2CenterX1() const { return fRadial2CenterX1; }
218 GrScalar getRadial2Radius0() const { return fRadial2Radius0; }
219 bool isRadial2PosRoot() const { return fRadial2PosRoot; }
bsalomon@google.com22c5dea2011-07-07 14:38:03 +0000220 // do the radial gradient params lead to a linear (rather than quadratic)
221 // equation.
222 bool radial2IsDegenerate() const { return GR_Scalar1 == fRadial2CenterX1; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000223
224 /**
bsalomon@google.com5782d712011-01-21 21:03:59 +0000225 * Sets the parameters for kRadial2_SampleMode. The texture
226 * matrix must be set so that the first point is at (0,0) and the second
reed@google.comac10a2d2010-12-22 21:39:39 +0000227 * point lies on the x-axis. The second radius minus the first is 1 unit.
228 * The additional parameters to define the gradient are specified by this
229 * function.
230 */
231 void setRadial2Params(GrScalar centerX1, GrScalar radius0, bool posRoot) {
232 fRadial2CenterX1 = centerX1;
233 fRadial2Radius0 = radius0;
234 fRadial2PosRoot = posRoot;
235 }
236
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000237 void setConvolutionParams(int kernelWidth, const float* kernel, float imageIncrement[2]) {
238 GrAssert(kernelWidth >= 0 && kernelWidth <= MAX_KERNEL_WIDTH);
239 fKernelWidth = kernelWidth;
240 if (NULL != kernel) {
241 memcpy(fKernel, kernel, kernelWidth * sizeof(float));
242 }
243 if (NULL != imageIncrement) {
244 memcpy(fImageIncrement, imageIncrement, sizeof(fImageIncrement));
245 } else {
246 memset(fImageIncrement, 0, sizeof(fImageIncrement));
247 }
248 }
249
reed@google.comac10a2d2010-12-22 21:39:39 +0000250 static const GrSamplerState& ClampNoFilter() {
251 return gClampNoFilter;
252 }
253
254private:
255 WrapMode fWrapX;
256 WrapMode fWrapY;
257 SampleMode fSampleMode;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000258 Filter fFilter;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000259 GrMatrix fMatrix;
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000260 bool fSwapRAndB;
junov@google.com6acc9b32011-05-16 18:32:07 +0000261 GrRect fTextureDomain;
reed@google.comac10a2d2010-12-22 21:39:39 +0000262
263 // these are undefined unless fSampleMode == kRadial2_SampleMode
264 GrScalar fRadial2CenterX1;
265 GrScalar fRadial2Radius0;
266 bool fRadial2PosRoot;
267
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000268 // These are undefined unless fFilter == kConvolution_Filter
269 int fKernelWidth;
270 float fKernel[MAX_KERNEL_WIDTH];
271 float fImageIncrement[2];
272
reed@google.comac10a2d2010-12-22 21:39:39 +0000273 static const GrSamplerState gClampNoFilter;
274};
275
276#endif
277