blob: 7e270f821855457c841eb41e6459fa9cd8088e39 [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 {
joshualitt5ae5fc52014-07-29 12:59:27 -070026 // Ignore the texture domain rectangle.
27 kIgnore_Mode,
28 // Clamp texture coords to the domain rectangle.
29 kClamp_Mode,
30 // Treat the area outside the domain rectangle as fully transparent.
31 kDecal_Mode,
32 // Wrap texture coordinates. NOTE: filtering may not work as expected because Bilerp will
33 // read texels outside of the domain. We could perform additional texture reads and filter
34 // in the shader, but are not currently doing this for performance reasons
35 kRepeat_Mode,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000036
joshualitt5ae5fc52014-07-29 12:59:27 -070037 kLastMode = kRepeat_Mode
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000038 };
39 static const int kModeCount = kLastMode + 1;
40
commit-bot@chromium.org7d7f3142013-12-16 15:18:11 +000041 static const GrTextureDomain& IgnoredDomain() {
42 static const SkRect gDummyRect = {0, 0, 0, 0};
43 static const GrTextureDomain gDomain(gDummyRect, kIgnore_Mode);
44 return gDomain;
45 }
46
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000047 /**
48 * @param index Pass a value >= 0 if using multiple texture domains in the same effect.
49 * It is used to keep inserted variables from causing name collisions.
50 */
51 GrTextureDomain(const SkRect& domain, Mode, int index = -1);
52
53 const SkRect& domain() const { return fDomain; }
54 Mode mode() const { return fMode; }
55
56 /* Computes a domain that bounds all the texels in texelRect. Note that with bilerp enabled
57 texels neighboring the domain may be read. */
58 static const SkRect MakeTexelDomain(const GrTexture* texture, const SkIRect& texelRect) {
59 SkScalar wInv = SK_Scalar1 / texture->width();
60 SkScalar hInv = SK_Scalar1 / texture->height();
61 SkRect result = {
62 texelRect.fLeft * wInv,
63 texelRect.fTop * hInv,
64 texelRect.fRight * wInv,
65 texelRect.fBottom * hInv
66 };
67 return result;
68 }
69
70 bool operator== (const GrTextureDomain& that) const {
71 return fMode == that.fMode && fDomain == that.fDomain;
72 }
73
74 /**
75 * A GrGLEffect subclass that corresponds to a GrEffect subclass that uses GrTextureDomain
76 * should include this helper. It generates the texture domain GLSL, produces the part of the
77 * effect key that reflects the texture domain code, and performs the uniform uploads necessary
78 * for texture domains.
79 */
80 class GLDomain {
81 public:
82 GLDomain() {
83 fPrevDomain[0] = SK_FloatNaN;
84 SkDEBUGCODE(fMode = (Mode) -1;)
85 }
86
87 /**
88 * Call this from GrGLEffect::emitCode() to sample the texture W.R.T. the domain and mode.
89 *
90 * @param outcolor name of vec4 variable to hold the sampled color.
91 * @param inCoords name of vec2 variable containing the coords to be used with the domain.
92 * It is assumed that this is a variable and not an expression.
93 * @param inModulateColor if non-NULL the sampled color will be modulated with this
94 * expression before being written to outColor.
95 */
96 void sampleTexture(GrGLShaderBuilder* builder,
97 const GrTextureDomain& textureDomain,
98 const char* outColor,
99 const SkString& inCoords,
100 const GrGLEffect::TextureSampler sampler,
101 const char* inModulateColor = NULL);
102
103 /**
104 * Call this from GrGLEffect::setData() to upload uniforms necessary for the texture domain.
105 * The rectangle is automatically adjusted to account for the texture's origin.
106 */
107 void setData(const GrGLUniformManager& uman, const GrTextureDomain& textureDomain,
108 GrSurfaceOrigin textureOrigin);
109
110 enum {
111 kDomainKeyBits = 2, // See DomainKey().
112 };
113
114 /**
115 * GrGLEffect::GenKey() must call this and include the returned value in it's computed key.
116 * The returned will be limited to the lower kDomainKeyBits bits.
117 */
bsalomon63e99f72014-07-21 08:03:14 -0700118 static uint32_t DomainKey(const GrTextureDomain& domain) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000119 GR_STATIC_ASSERT(kModeCount <= 4);
120 return domain.mode();
121 }
122
123 private:
124 SkDEBUGCODE(Mode fMode;)
125 GrGLUniformManager::UniformHandle fDomainUni;
126 SkString fDomainName;
127 GrGLfloat fPrevDomain[4];
128 };
129
130protected:
131 Mode fMode;
132 SkRect fDomain;
133 int fIndex;
134
135 typedef GrSingleTextureEffect INHERITED;
136};
137
138class GrGLTextureDomainEffect;
139
140/**
141 * A basic texture effect that uses GrTextureDomain.
142 */
143class GrTextureDomainEffect : public GrSingleTextureEffect {
144
145public:
bsalomon83d081a2014-07-08 09:56:10 -0700146 static GrEffect* Create(GrTexture*,
147 const SkMatrix&,
148 const SkRect& domain,
149 GrTextureDomain::Mode,
150 GrTextureParams::FilterMode filterMode,
151 GrCoordSet = kLocal_GrCoordSet);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000152
153 virtual ~GrTextureDomainEffect();
154
155 static const char* Name() { return "TextureDomain"; }
156
157 typedef GrGLTextureDomainEffect GLEffect;
158
159 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
160 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
161
162 const GrTextureDomain& textureDomain() const { return fTextureDomain; }
163
164protected:
165 GrTextureDomain fTextureDomain;
166
167private:
168 GrTextureDomainEffect(GrTexture*,
169 const SkMatrix&,
170 const SkRect& domain,
171 GrTextureDomain::Mode,
172 GrTextureParams::FilterMode,
173 GrCoordSet);
174
175 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
176
177 GR_DECLARE_EFFECT_TEST;
178
179 typedef GrSingleTextureEffect INHERITED;
180};
181
182#endif