|
1 /* |
|
2 * Copyright 2012 Google Inc. |
|
3 * |
|
4 * Use of this source code is governed by a BSD-style license that can be |
|
5 * found in the LICENSE file. |
|
6 */ |
|
7 |
|
8 #ifndef GrTextureDomainEffect_DEFINED |
|
9 #define GrTextureDomainEffect_DEFINED |
|
10 |
|
11 #include "GrSingleTextureEffect.h" |
|
12 #include "gl/GrGLEffect.h" |
|
13 |
|
14 class GrGLShaderBuilder; |
|
15 struct SkRect; |
|
16 |
|
17 /** |
|
18 * Limits a texture's lookup coordinates to a domain. Samples outside the domain are either clamped |
|
19 * the edge of the domain or result in a vec4 of zeros (decal mode). The domain is clipped to |
|
20 * normalized texture coords ([0,1]x[0,1] square). Bilinear filtering can cause texels outside the |
|
21 * domain to affect the read value unless the caller considers this when calculating the domain. |
|
22 */ |
|
23 class GrTextureDomain { |
|
24 public: |
|
25 enum Mode { |
|
26 kIgnore_Mode, // Ignore the texture domain rectangle. |
|
27 kClamp_Mode, // Clamp texture coords to the domain rectangle. |
|
28 kDecal_Mode, // Treat the area outside the domain rectangle as fully transparent. |
|
29 |
|
30 kLastMode = kDecal_Mode |
|
31 }; |
|
32 static const int kModeCount = kLastMode + 1; |
|
33 |
|
34 static const GrTextureDomain& IgnoredDomain() { |
|
35 static const SkRect gDummyRect = {0, 0, 0, 0}; |
|
36 static const GrTextureDomain gDomain(gDummyRect, kIgnore_Mode); |
|
37 return gDomain; |
|
38 } |
|
39 |
|
40 /** |
|
41 * @param index Pass a value >= 0 if using multiple texture domains in the same effect. |
|
42 * It is used to keep inserted variables from causing name collisions. |
|
43 */ |
|
44 GrTextureDomain(const SkRect& domain, Mode, int index = -1); |
|
45 |
|
46 const SkRect& domain() const { return fDomain; } |
|
47 Mode mode() const { return fMode; } |
|
48 |
|
49 /* Computes a domain that bounds all the texels in texelRect. Note that with bilerp enabled |
|
50 texels neighboring the domain may be read. */ |
|
51 static const SkRect MakeTexelDomain(const GrTexture* texture, const SkIRect& texelRect) { |
|
52 SkScalar wInv = SK_Scalar1 / texture->width(); |
|
53 SkScalar hInv = SK_Scalar1 / texture->height(); |
|
54 SkRect result = { |
|
55 texelRect.fLeft * wInv, |
|
56 texelRect.fTop * hInv, |
|
57 texelRect.fRight * wInv, |
|
58 texelRect.fBottom * hInv |
|
59 }; |
|
60 return result; |
|
61 } |
|
62 |
|
63 bool operator== (const GrTextureDomain& that) const { |
|
64 return fMode == that.fMode && fDomain == that.fDomain; |
|
65 } |
|
66 |
|
67 /** |
|
68 * A GrGLEffect subclass that corresponds to a GrEffect subclass that uses GrTextureDomain |
|
69 * should include this helper. It generates the texture domain GLSL, produces the part of the |
|
70 * effect key that reflects the texture domain code, and performs the uniform uploads necessary |
|
71 * for texture domains. |
|
72 */ |
|
73 class GLDomain { |
|
74 public: |
|
75 GLDomain() { |
|
76 fPrevDomain[0] = SK_FloatNaN; |
|
77 SkDEBUGCODE(fMode = (Mode) -1;) |
|
78 } |
|
79 |
|
80 /** |
|
81 * Call this from GrGLEffect::emitCode() to sample the texture W.R.T. the domain and mode. |
|
82 * |
|
83 * @param outcolor name of vec4 variable to hold the sampled color. |
|
84 * @param inCoords name of vec2 variable containing the coords to be used with the domain. |
|
85 * It is assumed that this is a variable and not an expression. |
|
86 * @param inModulateColor if non-NULL the sampled color will be modulated with this |
|
87 * expression before being written to outColor. |
|
88 */ |
|
89 void sampleTexture(GrGLShaderBuilder* builder, |
|
90 const GrTextureDomain& textureDomain, |
|
91 const char* outColor, |
|
92 const SkString& inCoords, |
|
93 const GrGLEffect::TextureSampler sampler, |
|
94 const char* inModulateColor = NULL); |
|
95 |
|
96 /** |
|
97 * Call this from GrGLEffect::setData() to upload uniforms necessary for the texture domain. |
|
98 * The rectangle is automatically adjusted to account for the texture's origin. |
|
99 */ |
|
100 void setData(const GrGLUniformManager& uman, const GrTextureDomain& textureDomain, |
|
101 GrSurfaceOrigin textureOrigin); |
|
102 |
|
103 enum { |
|
104 kDomainKeyBits = 2, // See DomainKey(). |
|
105 }; |
|
106 |
|
107 /** |
|
108 * GrGLEffect::GenKey() must call this and include the returned value in it's computed key. |
|
109 * The returned will be limited to the lower kDomainKeyBits bits. |
|
110 */ |
|
111 static GrGLEffect::EffectKey DomainKey(const GrTextureDomain& domain) { |
|
112 GR_STATIC_ASSERT(kModeCount <= 4); |
|
113 return domain.mode(); |
|
114 } |
|
115 |
|
116 private: |
|
117 SkDEBUGCODE(Mode fMode;) |
|
118 GrGLUniformManager::UniformHandle fDomainUni; |
|
119 SkString fDomainName; |
|
120 GrGLfloat fPrevDomain[4]; |
|
121 }; |
|
122 |
|
123 protected: |
|
124 Mode fMode; |
|
125 SkRect fDomain; |
|
126 int fIndex; |
|
127 |
|
128 typedef GrSingleTextureEffect INHERITED; |
|
129 }; |
|
130 |
|
131 class GrGLTextureDomainEffect; |
|
132 |
|
133 /** |
|
134 * A basic texture effect that uses GrTextureDomain. |
|
135 */ |
|
136 class GrTextureDomainEffect : public GrSingleTextureEffect { |
|
137 |
|
138 public: |
|
139 static GrEffectRef* Create(GrTexture*, |
|
140 const SkMatrix&, |
|
141 const SkRect& domain, |
|
142 GrTextureDomain::Mode, |
|
143 GrTextureParams::FilterMode filterMode, |
|
144 GrCoordSet = kLocal_GrCoordSet); |
|
145 |
|
146 virtual ~GrTextureDomainEffect(); |
|
147 |
|
148 static const char* Name() { return "TextureDomain"; } |
|
149 |
|
150 typedef GrGLTextureDomainEffect GLEffect; |
|
151 |
|
152 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; |
|
153 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; |
|
154 |
|
155 const GrTextureDomain& textureDomain() const { return fTextureDomain; } |
|
156 |
|
157 protected: |
|
158 GrTextureDomain fTextureDomain; |
|
159 |
|
160 private: |
|
161 GrTextureDomainEffect(GrTexture*, |
|
162 const SkMatrix&, |
|
163 const SkRect& domain, |
|
164 GrTextureDomain::Mode, |
|
165 GrTextureParams::FilterMode, |
|
166 GrCoordSet); |
|
167 |
|
168 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; |
|
169 |
|
170 GR_DECLARE_EFFECT_TEST; |
|
171 |
|
172 typedef GrSingleTextureEffect INHERITED; |
|
173 }; |
|
174 |
|
175 #endif |