blob: c7a4f2b3b828636848867bef4f456874a8bdac82 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#ifndef GrSamplerState_DEFINED
19#define GrSamplerState_DEFINED
20
21#include "GrTypes.h"
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000022#include "GrMatrix.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000023
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +000024#define MAX_KERNEL_WIDTH 25
25
reed@google.comac10a2d2010-12-22 21:39:39 +000026class GrSamplerState {
27public:
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +000028 enum Filter {
29 /**
30 * Read the closest src texel to the sample position
31 */
32 kNearest_Filter,
33 /**
34 * Blend between closest 4 src texels to sample position (tent filter)
35 */
36 kBilinear_Filter,
37 /**
38 * Average of 4 bilinear filterings spaced +/- 1 texel from sample
39 * position in x and y. Intended for averaging 16 texels in a downsample
40 * pass. (rasterizing such that texture samples fall exactly halfway
41 * between texels in x and y spaced 4 texels apart.)
42 */
43 k4x4Downsample_Filter,
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +000044 /**
45 * Apply a separable convolution kernel.
46 */
47 kConvolution_Filter
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +000048 };
49
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000050 /**
51 * The intepretation of the texture matrix depends on the sample mode. The
52 * texture matrix is applied both when the texture coordinates are explicit
53 * and when vertex positions are used as texture coordinates. In the latter
54 * case the texture matrix is applied to the pre-view-matrix position
55 * values.
56 *
57 * kNormal_SampleMode
58 * The post-matrix texture coordinates are in normalize space with (0,0) at
59 * the top-left and (1,1) at the bottom right.
60 * kRadial_SampleMode
61 * The matrix specifies the radial gradient parameters.
62 * (0,0) in the post-matrix space is center of the radial gradient.
63 * kRadial2_SampleMode
64 * Matrix transforms to space where first circle is centered at the
65 * origin. The second circle will be centered (x, 0) where x may be
66 * 0 and is provided by setRadial2Params. The post-matrix space is
67 * normalized such that 1 is the second radius - first radius.
68 * kSweepSampleMode
69 * The angle from the origin of texture coordinates in post-matrix space
70 * determines the gradient value.
71 */
reed@google.comac10a2d2010-12-22 21:39:39 +000072 enum SampleMode {
73 kNormal_SampleMode, //!< sample color directly
reed@google.comac10a2d2010-12-22 21:39:39 +000074 kRadial_SampleMode, //!< treat as radial gradient
75 kRadial2_SampleMode, //!< treat as 2-point radial gradient
76 kSweep_SampleMode, //!< treat as sweep gradient
77 };
78
79 /**
80 * Describes how a texture is sampled when coordinates are outside the
81 * texture border
82 */
83 enum WrapMode {
84 kClamp_WrapMode,
85 kRepeat_WrapMode,
86 kMirror_WrapMode
87 };
88
89 /**
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000090 * Default sampler state is set to clamp, use normal sampling mode, be
91 * unfiltered, and use identity matrix.
reed@google.comac10a2d2010-12-22 21:39:39 +000092 */
bsalomon@google.com6aab8e32011-06-21 20:32:12 +000093 GrSamplerState()
94 : fRadial2CenterX1()
95 , fRadial2Radius0()
96 , fRadial2PosRoot() {
reed@google.comac10a2d2010-12-22 21:39:39 +000097 this->setClampNoFilter();
98 }
99
bsalomon@google.com6aab8e32011-06-21 20:32:12 +0000100 explicit GrSamplerState(Filter filter)
101 : fRadial2CenterX1()
102 , fRadial2Radius0()
103 , fRadial2PosRoot() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000104 fWrapX = kClamp_WrapMode;
105 fWrapY = kClamp_WrapMode;
106 fSampleMode = kNormal_SampleMode;
107 fFilter = filter;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000108 fMatrix.setIdentity();
junov@google.com6acc9b32011-05-16 18:32:07 +0000109 fTextureDomain.setEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000110 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000111
bsalomon@google.com6aab8e32011-06-21 20:32:12 +0000112 GrSamplerState(WrapMode wx, WrapMode wy, Filter filter)
113 : fRadial2CenterX1()
114 , fRadial2Radius0()
115 , fRadial2PosRoot() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000116 fWrapX = wx;
117 fWrapY = wy;
118 fSampleMode = kNormal_SampleMode;
119 fFilter = filter;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000120 fMatrix.setIdentity();
junov@google.com6acc9b32011-05-16 18:32:07 +0000121 fTextureDomain.setEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000122 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000123
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000124 GrSamplerState(WrapMode wx, WrapMode wy,
bsalomon@google.com6aab8e32011-06-21 20:32:12 +0000125 const GrMatrix& matrix, Filter filter)
126 : fRadial2CenterX1()
127 , fRadial2Radius0()
128 , fRadial2PosRoot() {
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000129 fWrapX = wx;
130 fWrapY = wy;
131 fSampleMode = kNormal_SampleMode;
132 fFilter = filter;
133 fMatrix = matrix;
junov@google.com6acc9b32011-05-16 18:32:07 +0000134 fTextureDomain.setEmpty();
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000135 }
136
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000137 GrSamplerState(WrapMode wx, WrapMode wy, SampleMode sample,
bsalomon@google.com6aab8e32011-06-21 20:32:12 +0000138 const GrMatrix& matrix, Filter filter)
139 : fRadial2CenterX1()
140 , fRadial2Radius0()
141 , fRadial2PosRoot() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000142 fWrapX = wx;
143 fWrapY = wy;
144 fSampleMode = sample;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000145 fMatrix = matrix;
reed@google.comac10a2d2010-12-22 21:39:39 +0000146 fFilter = filter;
junov@google.com6acc9b32011-05-16 18:32:07 +0000147 fTextureDomain.setEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000148 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000149
reed@google.comac10a2d2010-12-22 21:39:39 +0000150 WrapMode getWrapX() const { return fWrapX; }
151 WrapMode getWrapY() const { return fWrapY; }
152 SampleMode getSampleMode() const { return fSampleMode; }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000153 const GrMatrix& getMatrix() const { return fMatrix; }
junov@google.com6acc9b32011-05-16 18:32:07 +0000154 const GrRect& getTextureDomain() const { return fTextureDomain; }
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000155 bool hasTextureDomain() const {return SkIntToScalar(0) != fTextureDomain.right();}
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000156 Filter getFilter() const { return fFilter; }
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000157 int getKernelWidth() const { return fKernelWidth; }
158 const float* getKernel() const { return fKernel; }
159 const float* getImageIncrement() const { return fImageIncrement; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000160
161 bool isGradient() const {
162 return kRadial_SampleMode == fSampleMode ||
163 kRadial2_SampleMode == fSampleMode ||
164 kSweep_SampleMode == fSampleMode;
165 }
166
167 void setWrapX(WrapMode mode) { fWrapX = mode; }
168 void setWrapY(WrapMode mode) { fWrapY = mode; }
169 void setSampleMode(SampleMode mode) { fSampleMode = mode; }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000170
171 /**
172 * Sets the sampler's matrix. See SampleMode for explanation of
173 * relationship between the matrix and sample mode.
174 * @param matrix the matrix to set
175 */
176 void setMatrix(const GrMatrix& matrix) { fMatrix = matrix; }
177
178 /**
junov@google.com6acc9b32011-05-16 18:32:07 +0000179 * Sets the sampler's texture coordinate domain to a
180 * custom rectangle, rather than the default (0,1).
181 * This option is currently only supported with kClamp_WrapMode
182 */
183 void setTextureDomain(const GrRect& textureDomain) { fTextureDomain = textureDomain; }
184
185 /**
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000186 * Multiplies the current sampler matrix a matrix
187 *
188 * After this call M' = M*m where M is the old matrix, m is the parameter
189 * to this function, and M' is the new matrix. (We consider points to
190 * be column vectors so tex cood vector t is transformed by matrix X as
191 * t' = X*t.)
192 *
193 * @param matrix the matrix used to modify the matrix.
194 */
195 void preConcatMatrix(const GrMatrix& matrix) { fMatrix.preConcat(matrix); }
196
197 /**
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000198 * Sets filtering type.
199 * @param filter type of filtering to apply
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000200 */
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000201 void setFilter(Filter filter) { fFilter = filter; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000202
203 void setClampNoFilter() {
204 fWrapX = kClamp_WrapMode;
205 fWrapY = kClamp_WrapMode;
206 fSampleMode = kNormal_SampleMode;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000207 fFilter = kNearest_Filter;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000208 fMatrix.setIdentity();
junov@google.com6acc9b32011-05-16 18:32:07 +0000209 fTextureDomain.setEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000210 }
211
212 GrScalar getRadial2CenterX1() const { return fRadial2CenterX1; }
213 GrScalar getRadial2Radius0() const { return fRadial2Radius0; }
214 bool isRadial2PosRoot() const { return fRadial2PosRoot; }
bsalomon@google.com22c5dea2011-07-07 14:38:03 +0000215 // do the radial gradient params lead to a linear (rather than quadratic)
216 // equation.
217 bool radial2IsDegenerate() const { return GR_Scalar1 == fRadial2CenterX1; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000218
219 /**
bsalomon@google.com5782d712011-01-21 21:03:59 +0000220 * Sets the parameters for kRadial2_SampleMode. The texture
221 * matrix must be set so that the first point is at (0,0) and the second
reed@google.comac10a2d2010-12-22 21:39:39 +0000222 * point lies on the x-axis. The second radius minus the first is 1 unit.
223 * The additional parameters to define the gradient are specified by this
224 * function.
225 */
226 void setRadial2Params(GrScalar centerX1, GrScalar radius0, bool posRoot) {
227 fRadial2CenterX1 = centerX1;
228 fRadial2Radius0 = radius0;
229 fRadial2PosRoot = posRoot;
230 }
231
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000232 void setConvolutionParams(int kernelWidth, const float* kernel, float imageIncrement[2]) {
233 GrAssert(kernelWidth >= 0 && kernelWidth <= MAX_KERNEL_WIDTH);
234 fKernelWidth = kernelWidth;
235 if (NULL != kernel) {
236 memcpy(fKernel, kernel, kernelWidth * sizeof(float));
237 }
238 if (NULL != imageIncrement) {
239 memcpy(fImageIncrement, imageIncrement, sizeof(fImageIncrement));
240 } else {
241 memset(fImageIncrement, 0, sizeof(fImageIncrement));
242 }
243 }
244
reed@google.comac10a2d2010-12-22 21:39:39 +0000245 static const GrSamplerState& ClampNoFilter() {
246 return gClampNoFilter;
247 }
248
249private:
250 WrapMode fWrapX;
251 WrapMode fWrapY;
252 SampleMode fSampleMode;
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000253 Filter fFilter;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000254 GrMatrix fMatrix;
junov@google.com6acc9b32011-05-16 18:32:07 +0000255 GrRect fTextureDomain;
reed@google.comac10a2d2010-12-22 21:39:39 +0000256
257 // these are undefined unless fSampleMode == kRadial2_SampleMode
258 GrScalar fRadial2CenterX1;
259 GrScalar fRadial2Radius0;
260 bool fRadial2PosRoot;
261
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000262 // These are undefined unless fFilter == kConvolution_Filter
263 int fKernelWidth;
264 float fKernel[MAX_KERNEL_WIDTH];
265 float fImageIncrement[2];
266
reed@google.comac10a2d2010-12-22 21:39:39 +0000267 static const GrSamplerState gClampNoFilter;
268};
269
270#endif
271