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 40 const SkRect& domain() const { return fDomain; } 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. */ 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: 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 */ 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 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 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