2 * Copyright 2012 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef GrTextureDomainEffect_DEFINED
9 #define GrTextureDomainEffect_DEFINED
11 #include "GrSingleTextureEffect.h"
12 #include "gl/GrGLProcessor.h"
14 class GrGLProgramBuilder;
15 class GrGLShaderBuilder;
16 class GrInvariantOutput;
20 * Limits a texture's lookup coordinates to a domain. Samples outside the domain are either clamped
21 * the edge of the domain or result in a vec4 of zeros (decal mode). The domain is clipped to
22 * normalized texture coords ([0,1]x[0,1] square). Bilinear filtering can cause texels outside the
23 * domain to affect the read value unless the caller considers this when calculating the domain.
25 class GrTextureDomain {
28 // Ignore the texture domain rectangle.
30 // Clamp texture coords to the domain rectangle.
32 // Treat the area outside the domain rectangle as fully transparent.
34 // Wrap texture coordinates. NOTE: filtering may not work as expected because Bilerp will
35 // read texels outside of the domain. We could perform additional texture reads and filter
36 // in the shader, but are not currently doing this for performance reasons
39 kLastMode = kRepeat_Mode
41 static const int kModeCount = kLastMode + 1;
43 static const GrTextureDomain& IgnoredDomain() {
44 static const SkRect gDummyRect = {0, 0, 0, 0};
45 static const GrTextureDomain gDomain(gDummyRect, kIgnore_Mode);
50 * @param index Pass a value >= 0 if using multiple texture domains in the same effect.
51 * It is used to keep inserted variables from causing name collisions.
53 GrTextureDomain(const SkRect& domain, Mode, int index = -1);
55 const SkRect& domain() const { return fDomain; }
56 Mode mode() const { return fMode; }
58 /* Computes a domain that bounds all the texels in texelRect. Note that with bilerp enabled
59 texels neighboring the domain may be read. */
60 static const SkRect MakeTexelDomain(const GrTexture* texture, const SkIRect& texelRect) {
61 SkScalar wInv = SK_Scalar1 / texture->width();
62 SkScalar hInv = SK_Scalar1 / texture->height();
64 texelRect.fLeft * wInv,
65 texelRect.fTop * hInv,
66 texelRect.fRight * wInv,
67 texelRect.fBottom * hInv
72 bool operator== (const GrTextureDomain& that) const {
73 return fMode == that.fMode && (kIgnore_Mode == fMode || fDomain == that.fDomain);
77 * A GrGLProcessor subclass that corresponds to a GrProcessor subclass that uses GrTextureDomain
78 * should include this helper. It generates the texture domain GLSL, produces the part of the
79 * effect key that reflects the texture domain code, and performs the uniform uploads necessary
80 * for texture domains.
85 fPrevDomain[0] = SK_FloatNaN;
86 SkDEBUGCODE(fMode = (Mode) -1;)
90 * Call this from GrGLProcessor::emitCode() to sample the texture W.R.T. the domain and
93 * @param outcolor name of vec4 variable to hold the sampled color.
94 * @param inCoords name of vec2 variable containing the coords to be used with the domain.
95 * It is assumed that this is a variable and not an expression.
96 * @param inModulateColor if non-NULL the sampled color will be modulated with this
97 * expression before being written to outColor.
99 void sampleTexture(GrGLShaderBuilder* builder,
100 const GrTextureDomain& textureDomain,
101 const char* outColor,
102 const SkString& inCoords,
103 const GrGLProcessor::TextureSampler sampler,
104 const char* inModulateColor = NULL);
107 * Call this from GrGLProcessor::setData() to upload uniforms necessary for the texture
108 * domain. The rectangle is automatically adjusted to account for the texture's origin.
110 void setData(const GrGLProgramDataManager& pdman, const GrTextureDomain& textureDomain,
111 GrSurfaceOrigin textureOrigin);
114 kDomainKeyBits = 2, // See DomainKey().
118 * GrGLProcessor::GenKey() must call this and include the returned value in it's computed
119 * key. The returned will be limited to the lower kDomainKeyBits bits.
121 static uint32_t DomainKey(const GrTextureDomain& domain) {
122 GR_STATIC_ASSERT(kModeCount <= 4);
123 return domain.mode();
127 SkDEBUGCODE(Mode fMode;)
128 GrGLProgramDataManager::UniformHandle fDomainUni;
129 SkString fDomainName;
130 GrGLfloat fPrevDomain[4];
138 typedef GrSingleTextureEffect INHERITED;
142 * A basic texture effect that uses GrTextureDomain.
144 class GrTextureDomainEffect : public GrSingleTextureEffect {
147 static GrFragmentProcessor* Create(GrTexture*,
149 const SkRect& domain,
150 GrTextureDomain::Mode,
151 GrTextureParams::FilterMode filterMode,
152 GrCoordSet = kLocal_GrCoordSet);
154 virtual ~GrTextureDomainEffect();
156 const char* name() const SK_OVERRIDE { return "TextureDomain"; }
158 void getGLProcessorKey(const GrGLCaps&, GrProcessorKeyBuilder*) const SK_OVERRIDE;
160 GrGLFragmentProcessor* createGLInstance() const SK_OVERRIDE;
162 const GrTextureDomain& textureDomain() const { return fTextureDomain; }
165 GrTextureDomain fTextureDomain;
168 GrTextureDomainEffect(GrTexture*,
170 const SkRect& domain,
171 GrTextureDomain::Mode,
172 GrTextureParams::FilterMode,
175 bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE;
177 void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE;
179 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
181 typedef GrSingleTextureEffect INHERITED;