• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
IgnoredDomain()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 
domain()46     const SkRect& domain() const { return fDomain; }
mode()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. */
MakeTexelDomain(const GrTexture * texture,const SkIRect & texelRect)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:
GLDomain()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          */
DomainKey(const GrTextureDomain & domain)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 
Name()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 
textureDomain()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
176