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