blob: b1c4852d7f5bdfefede571b08ebd6b51a48a8430 [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
tomhudson@google.com07eecdc2012-04-20 18:35:38 +000014#include "GrCustomStage.h"
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000015#include "GrMatrix.h"
tomhudson@google.com07eecdc2012-04-20 18:35:38 +000016#include "GrTypes.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000017
18class GrSamplerState {
19public:
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +000020 enum Filter {
21 /**
22 * Read the closest src texel to the sample position
23 */
24 kNearest_Filter,
25 /**
26 * Blend between closest 4 src texels to sample position (tent filter)
27 */
28 kBilinear_Filter,
29 /**
30 * Average of 4 bilinear filterings spaced +/- 1 texel from sample
31 * position in x and y. Intended for averaging 16 texels in a downsample
32 * pass. (rasterizing such that texture samples fall exactly halfway
bsalomon@google.com1f221a72011-08-23 20:54:07 +000033 * between texels in x and y spaced 4 texels apart.) Only supported
34 * on shader backends.
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +000035 */
36 k4x4Downsample_Filter,
bsalomon@google.comaa814fe2011-12-12 18:45:07 +000037
38 kDefault_Filter = kNearest_Filter
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +000039 };
40
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000041 /**
42 * The intepretation of the texture matrix depends on the sample mode. The
43 * texture matrix is applied both when the texture coordinates are explicit
44 * and when vertex positions are used as texture coordinates. In the latter
45 * case the texture matrix is applied to the pre-view-matrix position
46 * values.
47 *
48 * kNormal_SampleMode
49 * The post-matrix texture coordinates are in normalize space with (0,0) at
50 * the top-left and (1,1) at the bottom right.
51 * kRadial_SampleMode
52 * The matrix specifies the radial gradient parameters.
53 * (0,0) in the post-matrix space is center of the radial gradient.
54 * kRadial2_SampleMode
55 * Matrix transforms to space where first circle is centered at the
56 * origin. The second circle will be centered (x, 0) where x may be
57 * 0 and is provided by setRadial2Params. The post-matrix space is
58 * normalized such that 1 is the second radius - first radius.
59 * kSweepSampleMode
60 * The angle from the origin of texture coordinates in post-matrix space
61 * determines the gradient value.
62 */
reed@google.comac10a2d2010-12-22 21:39:39 +000063 enum SampleMode {
64 kNormal_SampleMode, //!< sample color directly
reed@google.comac10a2d2010-12-22 21:39:39 +000065 kRadial_SampleMode, //!< treat as radial gradient
66 kRadial2_SampleMode, //!< treat as 2-point radial gradient
67 kSweep_SampleMode, //!< treat as sweep gradient
bsalomon@google.comaa814fe2011-12-12 18:45:07 +000068
69 kDefault_SampleMode = kNormal_SampleMode
reed@google.comac10a2d2010-12-22 21:39:39 +000070 };
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,
bsalomon@google.comaa814fe2011-12-12 18:45:07 +000079 kMirror_WrapMode,
80
81 kDefault_WrapMode = kClamp_WrapMode
reed@google.comac10a2d2010-12-22 21:39:39 +000082 };
83
84 /**
bsalomon@google.comc6cf7232011-02-17 16:43:10 +000085 * Default sampler state is set to clamp, use normal sampling mode, be
86 * unfiltered, and use identity matrix.
reed@google.comac10a2d2010-12-22 21:39:39 +000087 */
bsalomon@google.com6aab8e32011-06-21 20:32:12 +000088 GrSamplerState()
tomhudson@google.comb88bbd22012-05-01 12:48:07 +000089 : fRadial2CenterX1()
bsalomon@google.com6aab8e32011-06-21 20:32:12 +000090 , fRadial2Radius0()
tomhudson@google.comb88bbd22012-05-01 12:48:07 +000091 , fRadial2PosRoot()
92 , fCustomStage (NULL) {
tomhudson@google.com194de082012-05-31 20:35:27 +000093 memset(this, 0, sizeof(GrSamplerState));
bsalomon@google.com97912912011-12-06 16:30:36 +000094 this->reset();
reed@google.comac10a2d2010-12-22 21:39:39 +000095 }
96
tomhudson@google.com07eecdc2012-04-20 18:35:38 +000097 ~GrSamplerState() {
98 GrSafeUnref(fCustomStage);
99 }
100
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000101 bool operator ==(const GrSamplerState& s) const {
tomhudson@google.comb88bbd22012-05-01 12:48:07 +0000102 /* We must be bit-identical as far as the CustomStage;
103 there may be multiple CustomStages that will produce
104 the same shader code and so are equivalent.
105 Can't take the address of fWrapX because it's :8 */
106 int bitwiseRegion = (intptr_t) &fCustomStage - (intptr_t) this;
107 GrAssert(sizeof(GrSamplerState) ==
108 bitwiseRegion + sizeof(fCustomStage));
109 return !memcmp(this, &s, bitwiseRegion) &&
110 ((fCustomStage == s.fCustomStage) ||
111 (fCustomStage && s.fCustomStage &&
tomhudson@google.comd8f856c2012-05-10 12:13:36 +0000112 (fCustomStage->getFactory() ==
113 s.fCustomStage->getFactory()) &&
bsalomon@google.comb505a122012-05-31 18:40:36 +0000114 fCustomStage->isEqual(*s.fCustomStage)));
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000115 }
116 bool operator !=(const GrSamplerState& s) const { return !(*this == s); }
117
tomhudson@google.com0bdbed32012-06-01 19:50:02 +0000118 GrSamplerState& operator =(const GrSamplerState& s) {
tomhudson@google.com11175592012-05-31 14:23:28 +0000119 // memcpy() breaks refcounting
120 fWrapX = s.fWrapX;
121 fWrapY = s.fWrapY;
tomhudson@google.com11175592012-05-31 14:23:28 +0000122 fSampleMode = s.fSampleMode;
123 fFilter = s.fFilter;
124 fMatrix = s.fMatrix;
125 fSwapRAndB = s.fSwapRAndB;
126 fTextureDomain = s.fTextureDomain;
127
128 fRadial2CenterX1 = s.fRadial2CenterX1;
129 fRadial2Radius0 = s.fRadial2Radius0;
130 fRadial2PosRoot = s.fRadial2PosRoot;
131
tomhudson@google.com11175592012-05-31 14:23:28 +0000132 fCustomStage = s.fCustomStage;
133 SkSafeRef(fCustomStage);
134
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000135 return *this;
136 }
137
reed@google.comac10a2d2010-12-22 21:39:39 +0000138 WrapMode getWrapX() const { return fWrapX; }
139 WrapMode getWrapY() const { return fWrapY; }
140 SampleMode getSampleMode() const { return fSampleMode; }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000141 const GrMatrix& getMatrix() const { return fMatrix; }
junov@google.com6acc9b32011-05-16 18:32:07 +0000142 const GrRect& getTextureDomain() const { return fTextureDomain; }
senorblanco@chromium.org64cc5792011-05-19 19:58:58 +0000143 bool hasTextureDomain() const {return SkIntToScalar(0) != fTextureDomain.right();}
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000144 Filter getFilter() const { return fFilter; }
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000145 bool swapsRAndB() const { return fSwapRAndB; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000146 bool isGradient() const {
147 return kRadial_SampleMode == fSampleMode ||
148 kRadial2_SampleMode == fSampleMode ||
149 kSweep_SampleMode == fSampleMode;
150 }
151
152 void setWrapX(WrapMode mode) { fWrapX = mode; }
153 void setWrapY(WrapMode mode) { fWrapY = mode; }
154 void setSampleMode(SampleMode mode) { fSampleMode = mode; }
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000155
156 /**
bsalomon@google.comaa814fe2011-12-12 18:45:07 +0000157 * Access the sampler's matrix. See SampleMode for explanation of
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000158 * relationship between the matrix and sample mode.
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000159 */
bsalomon@google.comaa814fe2011-12-12 18:45:07 +0000160 GrMatrix* matrix() { return &fMatrix; }
161
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000162 /**
junov@google.com6acc9b32011-05-16 18:32:07 +0000163 * Sets the sampler's texture coordinate domain to a
164 * custom rectangle, rather than the default (0,1).
165 * This option is currently only supported with kClamp_WrapMode
166 */
167 void setTextureDomain(const GrRect& textureDomain) { fTextureDomain = textureDomain; }
168
169 /**
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000170 * Swaps the R and B components when reading from the texture. Has no effect
171 * if the texture is alpha only.
172 */
173 void setRAndBSwap(bool swap) { fSwapRAndB = swap; }
174
175 /**
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000176 * Multiplies the current sampler matrix a matrix
177 *
178 * After this call M' = M*m where M is the old matrix, m is the parameter
179 * to this function, and M' is the new matrix. (We consider points to
180 * be column vectors so tex cood vector t is transformed by matrix X as
181 * t' = X*t.)
182 *
183 * @param matrix the matrix used to modify the matrix.
184 */
185 void preConcatMatrix(const GrMatrix& matrix) { fMatrix.preConcat(matrix); }
186
187 /**
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000188 * Sets filtering type.
189 * @param filter type of filtering to apply
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000190 */
bsalomon@google.com6aef1fb2011-05-05 12:33:22 +0000191 void setFilter(Filter filter) { fFilter = filter; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000192
bsalomon@google.com97912912011-12-06 16:30:36 +0000193 void reset(WrapMode wrapXAndY,
194 Filter filter,
195 const GrMatrix& matrix) {
196 fWrapX = wrapXAndY;
197 fWrapY = wrapXAndY;
bsalomon@google.comaa814fe2011-12-12 18:45:07 +0000198 fSampleMode = kDefault_SampleMode;
bsalomon@google.com97912912011-12-06 16:30:36 +0000199 fFilter = filter;
200 fMatrix = matrix;
201 fTextureDomain.setEmpty();
202 fSwapRAndB = false;
tomhudson@google.com07eecdc2012-04-20 18:35:38 +0000203 GrSafeSetNull(fCustomStage);
bsalomon@google.com97912912011-12-06 16:30:36 +0000204 }
bsalomon@google.comb505a122012-05-31 18:40:36 +0000205 void reset(WrapMode wrapXAndY, Filter filter) {
206 this->reset(wrapXAndY, filter, GrMatrix::I());
bsalomon@google.comaa814fe2011-12-12 18:45:07 +0000207 }
bsalomon@google.com1e266f82011-12-12 16:11:33 +0000208 void reset(const GrMatrix& matrix) {
bsalomon@google.comb505a122012-05-31 18:40:36 +0000209 this->reset(kDefault_WrapMode, kDefault_Filter, matrix);
bsalomon@google.comaa814fe2011-12-12 18:45:07 +0000210 }
211 void reset() {
bsalomon@google.comb505a122012-05-31 18:40:36 +0000212 this->reset(kDefault_WrapMode, kDefault_Filter, GrMatrix::I());
bsalomon@google.com1e266f82011-12-12 16:11:33 +0000213 }
bsalomon@google.com97912912011-12-06 16:30:36 +0000214
reed@google.comac10a2d2010-12-22 21:39:39 +0000215 GrScalar getRadial2CenterX1() const { return fRadial2CenterX1; }
216 GrScalar getRadial2Radius0() const { return fRadial2Radius0; }
bsalomon@google.come7160bf2011-11-10 15:28:16 +0000217 bool isRadial2PosRoot() const { return SkToBool(fRadial2PosRoot); }
bsalomon@google.com22c5dea2011-07-07 14:38:03 +0000218 // do the radial gradient params lead to a linear (rather than quadratic)
219 // equation.
220 bool radial2IsDegenerate() const { return GR_Scalar1 == fRadial2CenterX1; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000221
222 /**
bsalomon@google.com5782d712011-01-21 21:03:59 +0000223 * Sets the parameters for kRadial2_SampleMode. The texture
224 * matrix must be set so that the first point is at (0,0) and the second
reed@google.comac10a2d2010-12-22 21:39:39 +0000225 * point lies on the x-axis. The second radius minus the first is 1 unit.
226 * The additional parameters to define the gradient are specified by this
227 * function.
228 */
229 void setRadial2Params(GrScalar centerX1, GrScalar radius0, bool posRoot) {
230 fRadial2CenterX1 = centerX1;
231 fRadial2Radius0 = radius0;
232 fRadial2PosRoot = posRoot;
233 }
234
tomhudson@google.com07eecdc2012-04-20 18:35:38 +0000235 void setCustomStage(GrCustomStage* stage) {
236 GrSafeAssign(fCustomStage, stage);
237 }
238 GrCustomStage* getCustomStage() const { return fCustomStage; }
239
reed@google.comac10a2d2010-12-22 21:39:39 +0000240private:
senorblanco@chromium.org05054f12012-03-02 21:05:45 +0000241 WrapMode fWrapX : 8;
242 WrapMode fWrapY : 8;
senorblanco@chromium.org05054f12012-03-02 21:05:45 +0000243 SampleMode fSampleMode : 8;
244 Filter fFilter : 8;
245 GrMatrix fMatrix;
246 bool fSwapRAndB;
247 GrRect fTextureDomain;
reed@google.comac10a2d2010-12-22 21:39:39 +0000248
249 // these are undefined unless fSampleMode == kRadial2_SampleMode
senorblanco@chromium.org05054f12012-03-02 21:05:45 +0000250 GrScalar fRadial2CenterX1;
251 GrScalar fRadial2Radius0;
252 SkBool8 fRadial2PosRoot;
reed@google.comac10a2d2010-12-22 21:39:39 +0000253
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000254 GrCustomStage* fCustomStage;
reed@google.comac10a2d2010-12-22 21:39:39 +0000255};
256
257#endif
258