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