blob: 5751bad0f719656ff79392dc61a2c08b20a29020 [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"
joshualittb0a8a372014-09-23 09:50:21 -070012#include "gl/GrGLProcessor.h"
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000013
joshualitt30ba4362014-08-21 20:18:45 -070014class GrGLProgramBuilder;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000015class GrGLShaderBuilder;
16struct 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 */
24class GrTextureDomain {
25public:
26 enum Mode {
joshualitt5ae5fc52014-07-29 12:59:27 -070027 // 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,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000037
joshualitt5ae5fc52014-07-29 12:59:27 -070038 kLastMode = kRepeat_Mode
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000039 };
40 static const int kModeCount = kLastMode + 1;
41
commit-bot@chromium.org7d7f3142013-12-16 15:18:11 +000042 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
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000048 /**
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 {
egdaniel01a492f2014-08-21 06:47:50 -070072 return fMode == that.fMode && (kIgnore_Mode == fMode || fDomain == that.fDomain);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000073 }
74
75 /**
joshualittb0a8a372014-09-23 09:50:21 -070076 * A GrGLProcessor subclass that corresponds to a GrProcessor subclass that uses GrTextureDomain
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000077 * 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 /**
joshualittb0a8a372014-09-23 09:50:21 -070089 * Call this from GrGLProcessor::emitCode() to sample the texture W.R.T. the domain and
90 * mode.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000091 *
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,
joshualittb0a8a372014-09-23 09:50:21 -0700102 const GrGLProcessor::TextureSampler sampler,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000103 const char* inModulateColor = NULL);
104
105 /**
joshualittb0a8a372014-09-23 09:50:21 -0700106 * 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.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000108 */
kkinnunen7510b222014-07-30 00:04:16 -0700109 void setData(const GrGLProgramDataManager& pdman, const GrTextureDomain& textureDomain,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000110 GrSurfaceOrigin textureOrigin);
111
112 enum {
113 kDomainKeyBits = 2, // See DomainKey().
114 };
115
116 /**
joshualittb0a8a372014-09-23 09:50:21 -0700117 * 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.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000119 */
bsalomon63e99f72014-07-21 08:03:14 -0700120 static uint32_t DomainKey(const GrTextureDomain& domain) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000121 GR_STATIC_ASSERT(kModeCount <= 4);
122 return domain.mode();
123 }
124
125 private:
kkinnunen7510b222014-07-30 00:04:16 -0700126 SkDEBUGCODE(Mode fMode;)
127 GrGLProgramDataManager::UniformHandle fDomainUni;
128 SkString fDomainName;
129 GrGLfloat fPrevDomain[4];
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000130 };
131
132protected:
133 Mode fMode;
134 SkRect fDomain;
135 int fIndex;
136
137 typedef GrSingleTextureEffect INHERITED;
138};
139
140class GrGLTextureDomainEffect;
141
142/**
143 * A basic texture effect that uses GrTextureDomain.
144 */
145class GrTextureDomainEffect : public GrSingleTextureEffect {
146
147public:
joshualittb0a8a372014-09-23 09:50:21 -0700148 static GrFragmentProcessor* Create(GrTexture*,
149 const SkMatrix&,
150 const SkRect& domain,
151 GrTextureDomain::Mode,
152 GrTextureParams::FilterMode filterMode,
153 GrCoordSet = kLocal_GrCoordSet);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000154
155 virtual ~GrTextureDomainEffect();
156
157 static const char* Name() { return "TextureDomain"; }
158
joshualittb0a8a372014-09-23 09:50:21 -0700159 typedef GrGLTextureDomainEffect GLProcessor;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000160
joshualittb0a8a372014-09-23 09:50:21 -0700161 virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000162 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
163
164 const GrTextureDomain& textureDomain() const { return fTextureDomain; }
165
166protected:
167 GrTextureDomain fTextureDomain;
168
169private:
170 GrTextureDomainEffect(GrTexture*,
171 const SkMatrix&,
172 const SkRect& domain,
173 GrTextureDomain::Mode,
174 GrTextureParams::FilterMode,
175 GrCoordSet);
176
joshualittb0a8a372014-09-23 09:50:21 -0700177 virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000178
joshualittb0a8a372014-09-23 09:50:21 -0700179 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000180
181 typedef GrSingleTextureEffect INHERITED;
182};
183
184#endif