blob: 624e09fe5afc204e9948b5922324ea31c736df30 [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
34 * between texels in x and y spaced 4 texels apart.)
35 */
36 k4x4Downsample_Filter,
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +000037 /**
38 * Apply a separable convolution kernel.
39 */
40 kConvolution_Filter
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +000041 };
42
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000043 /**
44 * The intepretation of the texture matrix depends on the sample mode. The
45 * texture matrix is applied both when the texture coordinates are explicit
46 * and when vertex positions are used as texture coordinates. In the latter
47 * case the texture matrix is applied to the pre-view-matrix position
48 * values.
49 *
50 * kNormal_SampleMode
51 * The post-matrix texture coordinates are in normalize space with (0,0) at
52 * the top-left and (1,1) at the bottom right.
53 * kRadial_SampleMode
54 * The matrix specifies the radial gradient parameters.
55 * (0,0) in the post-matrix space is center of the radial gradient.
56 * kRadial2_SampleMode
57 * Matrix transforms to space where first circle is centered at the
58 * origin. The second circle will be centered (x, 0) where x may be
59 * 0 and is provided by setRadial2Params. The post-matrix space is
60 * normalized such that 1 is the second radius - first radius.
61 * kSweepSampleMode
62 * The angle from the origin of texture coordinates in post-matrix space
63 * determines the gradient value.
64 */
reed@google.comac10a2d2010-12-22 21:39:39 +000065 enum SampleMode {
66 kNormal_SampleMode, //!< sample color directly
reed@google.comac10a2d2010-12-22 21:39:39 +000067 kRadial_SampleMode, //!< treat as radial gradient
68 kRadial2_SampleMode, //!< treat as 2-point radial gradient
69 kSweep_SampleMode, //!< treat as sweep gradient
70 };
71
72 /**
73 * Describes how a texture is sampled when coordinates are outside the
74 * texture border
75 */
76 enum WrapMode {
77 kClamp_WrapMode,
78 kRepeat_WrapMode,
79 kMirror_WrapMode
80 };
81
82 /**
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000083 * Default sampler state is set to clamp, use normal sampling mode, be
84 * unfiltered, and use identity matrix.
reed@google.comac10a2d2010-12-22 21:39:39 +000085 */
bsalomon@google.com6aab8e32011-06-21 20:32:12 +000086 GrSamplerState()
87 : fRadial2CenterX1()
88 , fRadial2Radius0()
89 , fRadial2PosRoot() {
reed@google.comac10a2d2010-12-22 21:39:39 +000090 this->setClampNoFilter();
91 }
92
bsalomon@google.com6aab8e32011-06-21 20:32:12 +000093 explicit GrSamplerState(Filter filter)
94 : fRadial2CenterX1()
95 , fRadial2Radius0()
96 , fRadial2PosRoot() {
reed@google.comac10a2d2010-12-22 21:39:39 +000097 fWrapX = kClamp_WrapMode;
98 fWrapY = kClamp_WrapMode;
99 fSampleMode = kNormal_SampleMode;
100 fFilter = filter;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000101 fMatrix.setIdentity();
junov@google.com6acc9b32011-05-16 18:32:07 +0000102 fTextureDomain.setEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000103 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000104
bsalomon@google.com6aab8e32011-06-21 20:32:12 +0000105 GrSamplerState(WrapMode wx, WrapMode wy, Filter filter)
106 : fRadial2CenterX1()
107 , fRadial2Radius0()
108 , fRadial2PosRoot() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000109 fWrapX = wx;
110 fWrapY = wy;
111 fSampleMode = kNormal_SampleMode;
112 fFilter = filter;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000113 fMatrix.setIdentity();
junov@google.com6acc9b32011-05-16 18:32:07 +0000114 fTextureDomain.setEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000115 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000116
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000117 GrSamplerState(WrapMode wx, WrapMode wy,
bsalomon@google.com6aab8e32011-06-21 20:32:12 +0000118 const GrMatrix& matrix, Filter filter)
119 : fRadial2CenterX1()
120 , fRadial2Radius0()
121 , fRadial2PosRoot() {
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000122 fWrapX = wx;
123 fWrapY = wy;
124 fSampleMode = kNormal_SampleMode;
125 fFilter = filter;
126 fMatrix = matrix;
junov@google.com6acc9b32011-05-16 18:32:07 +0000127 fTextureDomain.setEmpty();
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000128 }
129
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000130 GrSamplerState(WrapMode wx, WrapMode wy, SampleMode sample,
bsalomon@google.com6aab8e32011-06-21 20:32:12 +0000131 const GrMatrix& matrix, Filter filter)
132 : fRadial2CenterX1()
133 , fRadial2Radius0()
134 , fRadial2PosRoot() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000135 fWrapX = wx;
136 fWrapY = wy;
137 fSampleMode = sample;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000138 fMatrix = matrix;
reed@google.comac10a2d2010-12-22 21:39:39 +0000139 fFilter = filter;
junov@google.com6acc9b32011-05-16 18:32:07 +0000140 fTextureDomain.setEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000141 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000142
reed@google.comac10a2d2010-12-22 21:39:39 +0000143 WrapMode getWrapX() const { return fWrapX; }
144 WrapMode getWrapY() const { return fWrapY; }
145 SampleMode getSampleMode() const { return fSampleMode; }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000146 const GrMatrix& getMatrix() const { return fMatrix; }
junov@google.com6acc9b32011-05-16 18:32:07 +0000147 const GrRect& getTextureDomain() const { return fTextureDomain; }
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000148 bool hasTextureDomain() const {return SkIntToScalar(0) != fTextureDomain.right();}
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000149 Filter getFilter() const { return fFilter; }
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000150 int getKernelWidth() const { return fKernelWidth; }
151 const float* getKernel() const { return fKernel; }
152 const float* getImageIncrement() const { return fImageIncrement; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000153
154 bool isGradient() const {
155 return kRadial_SampleMode == fSampleMode ||
156 kRadial2_SampleMode == fSampleMode ||
157 kSweep_SampleMode == fSampleMode;
158 }
159
160 void setWrapX(WrapMode mode) { fWrapX = mode; }
161 void setWrapY(WrapMode mode) { fWrapY = mode; }
162 void setSampleMode(SampleMode mode) { fSampleMode = mode; }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000163
164 /**
165 * Sets the sampler's matrix. See SampleMode for explanation of
166 * relationship between the matrix and sample mode.
167 * @param matrix the matrix to set
168 */
169 void setMatrix(const GrMatrix& matrix) { fMatrix = matrix; }
170
171 /**
junov@google.com6acc9b32011-05-16 18:32:07 +0000172 * Sets the sampler's texture coordinate domain to a
173 * custom rectangle, rather than the default (0,1).
174 * This option is currently only supported with kClamp_WrapMode
175 */
176 void setTextureDomain(const GrRect& textureDomain) { fTextureDomain = textureDomain; }
177
178 /**
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000179 * Multiplies the current sampler matrix a matrix
180 *
181 * After this call M' = M*m where M is the old matrix, m is the parameter
182 * to this function, and M' is the new matrix. (We consider points to
183 * be column vectors so tex cood vector t is transformed by matrix X as
184 * t' = X*t.)
185 *
186 * @param matrix the matrix used to modify the matrix.
187 */
188 void preConcatMatrix(const GrMatrix& matrix) { fMatrix.preConcat(matrix); }
189
190 /**
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000191 * Sets filtering type.
192 * @param filter type of filtering to apply
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000193 */
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000194 void setFilter(Filter filter) { fFilter = filter; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000195
196 void setClampNoFilter() {
197 fWrapX = kClamp_WrapMode;
198 fWrapY = kClamp_WrapMode;
199 fSampleMode = kNormal_SampleMode;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000200 fFilter = kNearest_Filter;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000201 fMatrix.setIdentity();
junov@google.com6acc9b32011-05-16 18:32:07 +0000202 fTextureDomain.setEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000203 }
204
205 GrScalar getRadial2CenterX1() const { return fRadial2CenterX1; }
206 GrScalar getRadial2Radius0() const { return fRadial2Radius0; }
207 bool isRadial2PosRoot() const { return fRadial2PosRoot; }
bsalomon@google.com22c5dea2011-07-07 14:38:03 +0000208 // do the radial gradient params lead to a linear (rather than quadratic)
209 // equation.
210 bool radial2IsDegenerate() const { return GR_Scalar1 == fRadial2CenterX1; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000211
212 /**
bsalomon@google.com5782d712011-01-21 21:03:59 +0000213 * Sets the parameters for kRadial2_SampleMode. The texture
214 * matrix must be set so that the first point is at (0,0) and the second
reed@google.comac10a2d2010-12-22 21:39:39 +0000215 * point lies on the x-axis. The second radius minus the first is 1 unit.
216 * The additional parameters to define the gradient are specified by this
217 * function.
218 */
219 void setRadial2Params(GrScalar centerX1, GrScalar radius0, bool posRoot) {
220 fRadial2CenterX1 = centerX1;
221 fRadial2Radius0 = radius0;
222 fRadial2PosRoot = posRoot;
223 }
224
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000225 void setConvolutionParams(int kernelWidth, const float* kernel, float imageIncrement[2]) {
226 GrAssert(kernelWidth >= 0 && kernelWidth <= MAX_KERNEL_WIDTH);
227 fKernelWidth = kernelWidth;
228 if (NULL != kernel) {
229 memcpy(fKernel, kernel, kernelWidth * sizeof(float));
230 }
231 if (NULL != imageIncrement) {
232 memcpy(fImageIncrement, imageIncrement, sizeof(fImageIncrement));
233 } else {
234 memset(fImageIncrement, 0, sizeof(fImageIncrement));
235 }
236 }
237
reed@google.comac10a2d2010-12-22 21:39:39 +0000238 static const GrSamplerState& ClampNoFilter() {
239 return gClampNoFilter;
240 }
241
242private:
243 WrapMode fWrapX;
244 WrapMode fWrapY;
245 SampleMode fSampleMode;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000246 Filter fFilter;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000247 GrMatrix fMatrix;
junov@google.com6acc9b32011-05-16 18:32:07 +0000248 GrRect fTextureDomain;
reed@google.comac10a2d2010-12-22 21:39:39 +0000249
250 // these are undefined unless fSampleMode == kRadial2_SampleMode
251 GrScalar fRadial2CenterX1;
252 GrScalar fRadial2Radius0;
253 bool fRadial2PosRoot;
254
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000255 // These are undefined unless fFilter == kConvolution_Filter
256 int fKernelWidth;
257 float fKernel[MAX_KERNEL_WIDTH];
258 float fImageIncrement[2];
259
reed@google.comac10a2d2010-12-22 21:39:39 +0000260 static const GrSamplerState gClampNoFilter;
261};
262
263#endif
264