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