• 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 
34     /**
35      * @param index     Pass a value >= 0 if using multiple texture domains in the same effect.
36      *                  It is used to keep inserted variables from causing name collisions.
37      */
38     GrTextureDomain(const SkRect& domain, Mode, int index = -1);
39 
domain()40     const SkRect& domain() const { return fDomain; }
mode()41     Mode mode() const { return fMode; }
42 
43     /* Computes a domain that bounds all the texels in texelRect. Note that with bilerp enabled
44        texels neighboring the domain may be read. */
MakeTexelDomain(const GrTexture * texture,const SkIRect & texelRect)45     static const SkRect MakeTexelDomain(const GrTexture* texture, const SkIRect& texelRect) {
46         SkScalar wInv = SK_Scalar1 / texture->width();
47         SkScalar hInv = SK_Scalar1 / texture->height();
48         SkRect result = {
49             texelRect.fLeft * wInv,
50             texelRect.fTop * hInv,
51             texelRect.fRight * wInv,
52             texelRect.fBottom * hInv
53         };
54         return result;
55     }
56 
57     bool operator== (const GrTextureDomain& that) const {
58         return fMode == that.fMode && fDomain == that.fDomain;
59     }
60 
61     /**
62      * A GrGLEffect subclass that corresponds to a GrEffect subclass that uses GrTextureDomain
63      * should include this helper. It generates the texture domain GLSL, produces the part of the
64      * effect key that reflects the texture domain code, and performs the uniform uploads necessary
65      * for texture domains.
66      */
67     class GLDomain {
68     public:
GLDomain()69         GLDomain() {
70             fPrevDomain[0] = SK_FloatNaN;
71             SkDEBUGCODE(fMode = (Mode) -1;)
72         }
73 
74         /**
75          * Call this from GrGLEffect::emitCode() to sample the texture W.R.T. the domain and mode.
76          *
77          * @param outcolor  name of vec4 variable to hold the sampled color.
78          * @param inCoords  name of vec2 variable containing the coords to be used with the domain.
79          *                  It is assumed that this is a variable and not an expression.
80          * @param inModulateColor   if non-NULL the sampled color will be modulated with this
81          *                          expression before being written to outColor.
82          */
83         void sampleTexture(GrGLShaderBuilder* builder,
84                            const GrTextureDomain& textureDomain,
85                            const char* outColor,
86                            const SkString& inCoords,
87                            const GrGLEffect::TextureSampler sampler,
88                            const char* inModulateColor = NULL);
89 
90         /**
91          * Call this from GrGLEffect::setData() to upload uniforms necessary for the texture domain.
92          * The rectangle is automatically adjusted to account for the texture's origin.
93          */
94         void setData(const GrGLUniformManager& uman, const GrTextureDomain& textureDomain,
95                      GrSurfaceOrigin textureOrigin);
96 
97         enum {
98             kDomainKeyBits = 2, // See DomainKey().
99         };
100 
101         /**
102          * GrGLEffect::GenKey() must call this and include the returned value in it's computed key.
103          * The returned will be limited to the lower kDomainKeyBits bits.
104          */
DomainKey(const GrTextureDomain & domain)105         static GrGLEffect::EffectKey DomainKey(const GrTextureDomain& domain) {
106             GR_STATIC_ASSERT(kModeCount <= 4);
107             return domain.mode();
108         }
109 
110     private:
111         SkDEBUGCODE(Mode                  fMode;)
112         GrGLUniformManager::UniformHandle fDomainUni;
113         SkString                          fDomainName;
114         GrGLfloat                         fPrevDomain[4];
115     };
116 
117 protected:
118     Mode    fMode;
119     SkRect  fDomain;
120     int     fIndex;
121 
122     typedef GrSingleTextureEffect INHERITED;
123 };
124 
125 class GrGLTextureDomainEffect;
126 
127 /**
128  * A basic texture effect that uses GrTextureDomain.
129  */
130 class GrTextureDomainEffect : public GrSingleTextureEffect {
131 
132 public:
133     static GrEffectRef* Create(GrTexture*,
134                                const SkMatrix&,
135                                const SkRect& domain,
136                                GrTextureDomain::Mode,
137                                GrTextureParams::FilterMode filterMode,
138                                GrCoordSet = kLocal_GrCoordSet);
139 
140     virtual ~GrTextureDomainEffect();
141 
Name()142     static const char* Name() { return "TextureDomain"; }
143 
144     typedef GrGLTextureDomainEffect GLEffect;
145 
146     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
147     virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
148 
textureDomain()149     const GrTextureDomain& textureDomain() const { return fTextureDomain; }
150 
151 protected:
152     GrTextureDomain fTextureDomain;
153 
154 private:
155     GrTextureDomainEffect(GrTexture*,
156                           const SkMatrix&,
157                           const SkRect& domain,
158                           GrTextureDomain::Mode,
159                           GrTextureParams::FilterMode,
160                           GrCoordSet);
161 
162     virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
163 
164     GR_DECLARE_EFFECT_TEST;
165 
166     typedef GrSingleTextureEffect INHERITED;
167 };
168 
169 #endif
170