blob: f64d5c3cf5865dbdb53726d33759524cfa0d3a97 [file] [log] [blame]
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +00001/*
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
14class GrGLShaderBuilder;
15struct 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 */
23class GrTextureDomain {
24public:
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
117protected:
118 Mode fMode;
119 SkRect fDomain;
120 int fIndex;
121
122 typedef GrSingleTextureEffect INHERITED;
123};
124
125class GrGLTextureDomainEffect;
126
127/**
128 * A basic texture effect that uses GrTextureDomain.
129 */
130class GrTextureDomainEffect : public GrSingleTextureEffect {
131
132public:
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
151protected:
152 GrTextureDomain fTextureDomain;
153
154private:
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