Home | History | Annotate | Download | only in effects
      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
    176