blob: 81dfdb3969d5ef567d2971dbd7a19d29d7f9d5e2 [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 */
bsalomon@google.comaa814fe2011-12-12 18:45:07 +000041 kConvolution_Filter,
42
43 kDefault_Filter = kNearest_Filter
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +000044 };
45
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000046 /**
47 * The intepretation of the texture matrix depends on the sample mode. The
48 * texture matrix is applied both when the texture coordinates are explicit
49 * and when vertex positions are used as texture coordinates. In the latter
50 * case the texture matrix is applied to the pre-view-matrix position
51 * values.
52 *
53 * kNormal_SampleMode
54 * The post-matrix texture coordinates are in normalize space with (0,0) at
55 * the top-left and (1,1) at the bottom right.
56 * kRadial_SampleMode
57 * The matrix specifies the radial gradient parameters.
58 * (0,0) in the post-matrix space is center of the radial gradient.
59 * kRadial2_SampleMode
60 * Matrix transforms to space where first circle is centered at the
61 * origin. The second circle will be centered (x, 0) where x may be
62 * 0 and is provided by setRadial2Params. The post-matrix space is
63 * normalized such that 1 is the second radius - first radius.
64 * kSweepSampleMode
65 * The angle from the origin of texture coordinates in post-matrix space
66 * determines the gradient value.
67 */
reed@google.comac10a2d2010-12-22 21:39:39 +000068 enum SampleMode {
69 kNormal_SampleMode, //!< sample color directly
reed@google.comac10a2d2010-12-22 21:39:39 +000070 kRadial_SampleMode, //!< treat as radial gradient
71 kRadial2_SampleMode, //!< treat as 2-point radial gradient
72 kSweep_SampleMode, //!< treat as sweep gradient
bsalomon@google.comaa814fe2011-12-12 18:45:07 +000073
74 kDefault_SampleMode = kNormal_SampleMode
reed@google.comac10a2d2010-12-22 21:39:39 +000075 };
76
77 /**
78 * Describes how a texture is sampled when coordinates are outside the
79 * texture border
80 */
81 enum WrapMode {
82 kClamp_WrapMode,
83 kRepeat_WrapMode,
bsalomon@google.comaa814fe2011-12-12 18:45:07 +000084 kMirror_WrapMode,
85
86 kDefault_WrapMode = kClamp_WrapMode
reed@google.comac10a2d2010-12-22 21:39:39 +000087 };
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() {
bsalomon@google.com97912912011-12-06 16:30:36 +000097 this->reset();
reed@google.comac10a2d2010-12-22 21:39:39 +000098 }
99
reed@google.comac10a2d2010-12-22 21:39:39 +0000100 WrapMode getWrapX() const { return fWrapX; }
101 WrapMode getWrapY() const { return fWrapY; }
102 SampleMode getSampleMode() const { return fSampleMode; }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000103 const GrMatrix& getMatrix() const { return fMatrix; }
junov@google.com6acc9b32011-05-16 18:32:07 +0000104 const GrRect& getTextureDomain() const { return fTextureDomain; }
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000105 bool hasTextureDomain() const {return SkIntToScalar(0) != fTextureDomain.right();}
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000106 Filter getFilter() const { return fFilter; }
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000107 int getKernelWidth() const { return fKernelWidth; }
108 const float* getKernel() const { return fKernel; }
109 const float* getImageIncrement() const { return fImageIncrement; }
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000110 bool swapsRAndB() const { return fSwapRAndB; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000111
112 bool isGradient() const {
113 return kRadial_SampleMode == fSampleMode ||
114 kRadial2_SampleMode == fSampleMode ||
115 kSweep_SampleMode == fSampleMode;
116 }
117
118 void setWrapX(WrapMode mode) { fWrapX = mode; }
119 void setWrapY(WrapMode mode) { fWrapY = mode; }
120 void setSampleMode(SampleMode mode) { fSampleMode = mode; }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000121
122 /**
bsalomon@google.comaa814fe2011-12-12 18:45:07 +0000123 * Access the sampler's matrix. See SampleMode for explanation of
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000124 * relationship between the matrix and sample mode.
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000125 */
bsalomon@google.comaa814fe2011-12-12 18:45:07 +0000126 GrMatrix* matrix() { return &fMatrix; }
127
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000128 /**
junov@google.com6acc9b32011-05-16 18:32:07 +0000129 * Sets the sampler's texture coordinate domain to a
130 * custom rectangle, rather than the default (0,1).
131 * This option is currently only supported with kClamp_WrapMode
132 */
133 void setTextureDomain(const GrRect& textureDomain) { fTextureDomain = textureDomain; }
134
135 /**
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000136 * Swaps the R and B components when reading from the texture. Has no effect
137 * if the texture is alpha only.
138 */
139 void setRAndBSwap(bool swap) { fSwapRAndB = swap; }
140
141 /**
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000142 * Multiplies the current sampler matrix a matrix
143 *
144 * After this call M' = M*m where M is the old matrix, m is the parameter
145 * to this function, and M' is the new matrix. (We consider points to
146 * be column vectors so tex cood vector t is transformed by matrix X as
147 * t' = X*t.)
148 *
149 * @param matrix the matrix used to modify the matrix.
150 */
151 void preConcatMatrix(const GrMatrix& matrix) { fMatrix.preConcat(matrix); }
152
153 /**
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000154 * Sets filtering type.
155 * @param filter type of filtering to apply
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000156 */
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000157 void setFilter(Filter filter) { fFilter = filter; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000158
bsalomon@google.com97912912011-12-06 16:30:36 +0000159 void reset(WrapMode wrapXAndY,
160 Filter filter,
161 const GrMatrix& matrix) {
162 fWrapX = wrapXAndY;
163 fWrapY = wrapXAndY;
bsalomon@google.comaa814fe2011-12-12 18:45:07 +0000164 fSampleMode = kDefault_SampleMode;
bsalomon@google.com97912912011-12-06 16:30:36 +0000165 fFilter = filter;
166 fMatrix = matrix;
167 fTextureDomain.setEmpty();
168 fSwapRAndB = false;
169 }
bsalomon@google.comaa814fe2011-12-12 18:45:07 +0000170 void reset(WrapMode wrapXAndY,
171 Filter filter) {
172 this->reset(wrapXAndY, filter, GrMatrix::I());
173 }
bsalomon@google.com1e266f82011-12-12 16:11:33 +0000174 void reset(const GrMatrix& matrix) {
bsalomon@google.comaa814fe2011-12-12 18:45:07 +0000175 this->reset(kDefault_WrapMode, kDefault_Filter, matrix);
176 }
177 void reset() {
178 this->reset(kDefault_WrapMode, kDefault_Filter, GrMatrix::I());
bsalomon@google.com1e266f82011-12-12 16:11:33 +0000179 }
bsalomon@google.com97912912011-12-06 16:30:36 +0000180
reed@google.comac10a2d2010-12-22 21:39:39 +0000181 GrScalar getRadial2CenterX1() const { return fRadial2CenterX1; }
182 GrScalar getRadial2Radius0() const { return fRadial2Radius0; }
bsalomon@google.come7160bf2011-11-10 15:28:16 +0000183 bool isRadial2PosRoot() const { return SkToBool(fRadial2PosRoot); }
bsalomon@google.com22c5dea2011-07-07 14:38:03 +0000184 // do the radial gradient params lead to a linear (rather than quadratic)
185 // equation.
186 bool radial2IsDegenerate() const { return GR_Scalar1 == fRadial2CenterX1; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000187
188 /**
bsalomon@google.com5782d712011-01-21 21:03:59 +0000189 * Sets the parameters for kRadial2_SampleMode. The texture
190 * matrix must be set so that the first point is at (0,0) and the second
reed@google.comac10a2d2010-12-22 21:39:39 +0000191 * point lies on the x-axis. The second radius minus the first is 1 unit.
192 * The additional parameters to define the gradient are specified by this
193 * function.
194 */
195 void setRadial2Params(GrScalar centerX1, GrScalar radius0, bool posRoot) {
196 fRadial2CenterX1 = centerX1;
197 fRadial2Radius0 = radius0;
198 fRadial2PosRoot = posRoot;
199 }
200
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000201 void setConvolutionParams(int kernelWidth, const float* kernel, float imageIncrement[2]) {
202 GrAssert(kernelWidth >= 0 && kernelWidth <= MAX_KERNEL_WIDTH);
203 fKernelWidth = kernelWidth;
204 if (NULL != kernel) {
205 memcpy(fKernel, kernel, kernelWidth * sizeof(float));
206 }
207 if (NULL != imageIncrement) {
208 memcpy(fImageIncrement, imageIncrement, sizeof(fImageIncrement));
209 } else {
210 memset(fImageIncrement, 0, sizeof(fImageIncrement));
211 }
212 }
213
reed@google.comac10a2d2010-12-22 21:39:39 +0000214private:
tomhudson@google.com62b09682011-11-09 16:39:17 +0000215 WrapMode fWrapX : 8;
216 WrapMode fWrapY : 8;
217 SampleMode fSampleMode : 8;
218 Filter fFilter : 8;
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000219 GrMatrix fMatrix;
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000220 bool fSwapRAndB;
junov@google.com6acc9b32011-05-16 18:32:07 +0000221 GrRect fTextureDomain;
reed@google.comac10a2d2010-12-22 21:39:39 +0000222
223 // these are undefined unless fSampleMode == kRadial2_SampleMode
224 GrScalar fRadial2CenterX1;
225 GrScalar fRadial2Radius0;
tomhudson@google.com62b09682011-11-09 16:39:17 +0000226 SkBool8 fRadial2PosRoot;
reed@google.comac10a2d2010-12-22 21:39:39 +0000227
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000228 // These are undefined unless fFilter == kConvolution_Filter
tomhudson@google.com62b09682011-11-09 16:39:17 +0000229 uint8_t fKernelWidth;
senorblanco@chromium.org027de5f2011-07-08 18:03:33 +0000230 float fImageIncrement[2];
tomhudson@google.com62b09682011-11-09 16:39:17 +0000231 float fKernel[MAX_KERNEL_WIDTH];
reed@google.comac10a2d2010-12-22 21:39:39 +0000232};
233
234#endif
235