blob: 80a617ef722eff937f9eb1ef381b97b83768605b [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
commit-bot@chromium.org7d7f3142013-12-16 15:18:11 +000034 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
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000040 /**
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
46 const SkRect& domain() const { return fDomain; }
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. */
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:
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 */
bsalomon63e99f72014-07-21 08:03:14 -0700111 static uint32_t DomainKey(const GrTextureDomain& domain) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000112 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
123protected:
124 Mode fMode;
125 SkRect fDomain;
126 int fIndex;
127
128 typedef GrSingleTextureEffect INHERITED;
129};
130
131class GrGLTextureDomainEffect;
132
133/**
134 * A basic texture effect that uses GrTextureDomain.
135 */
136class GrTextureDomainEffect : public GrSingleTextureEffect {
137
138public:
bsalomon83d081a2014-07-08 09:56:10 -0700139 static GrEffect* Create(GrTexture*,
140 const SkMatrix&,
141 const SkRect& domain,
142 GrTextureDomain::Mode,
143 GrTextureParams::FilterMode filterMode,
144 GrCoordSet = kLocal_GrCoordSet);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000145
146 virtual ~GrTextureDomainEffect();
147
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
155 const GrTextureDomain& textureDomain() const { return fTextureDomain; }
156
157protected:
158 GrTextureDomain fTextureDomain;
159
160private:
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