blob: 11760fb62b5929433acf49226105f8f883e906a7 [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"
wangyix6af0c932015-07-22 10:21:17 -070012#include "gl/GrGLFragmentProcessor.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;
egdaniel605dd0f2014-11-12 08:35:25 -080016class GrInvariantOutput;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000017struct SkRect;
18
19/**
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.
24 */
25class GrTextureDomain {
26public:
27 enum Mode {
joshualitt5ae5fc52014-07-29 12:59:27 -070028 // Ignore the texture domain rectangle.
29 kIgnore_Mode,
30 // Clamp texture coords to the domain rectangle.
31 kClamp_Mode,
32 // Treat the area outside the domain rectangle as fully transparent.
33 kDecal_Mode,
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
37 kRepeat_Mode,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000038
joshualitt5ae5fc52014-07-29 12:59:27 -070039 kLastMode = kRepeat_Mode
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000040 };
41 static const int kModeCount = kLastMode + 1;
42
commit-bot@chromium.org7d7f3142013-12-16 15:18:11 +000043 static const GrTextureDomain& IgnoredDomain() {
44 static const SkRect gDummyRect = {0, 0, 0, 0};
45 static const GrTextureDomain gDomain(gDummyRect, kIgnore_Mode);
46 return gDomain;
47 }
48
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000049 /**
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.
52 */
53 GrTextureDomain(const SkRect& domain, Mode, int index = -1);
54
55 const SkRect& domain() const { return fDomain; }
56 Mode mode() const { return fMode; }
57
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();
63 SkRect result = {
64 texelRect.fLeft * wInv,
65 texelRect.fTop * hInv,
66 texelRect.fRight * wInv,
67 texelRect.fBottom * hInv
68 };
69 return result;
70 }
71
senorblancod0d37ca2015-04-02 04:54:56 -070072 static const SkRect MakeTexelDomainForMode(const GrTexture* texture, const SkIRect& texelRect, Mode mode) {
73 // For Clamp mode, inset by half a texel.
74 SkScalar wInv = SK_Scalar1 / texture->width();
75 SkScalar hInv = SK_Scalar1 / texture->height();
76 SkScalar inset = (mode == kClamp_Mode && !texelRect.isEmpty()) ? SK_ScalarHalf : 0;
77 return SkRect::MakeLTRB(
78 (texelRect.fLeft + inset) * wInv,
79 (texelRect.fTop + inset) * hInv,
80 (texelRect.fRight - inset) * wInv,
81 (texelRect.fBottom - inset) * hInv
82 );
83 }
84
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000085 bool operator== (const GrTextureDomain& that) const {
egdaniel01a492f2014-08-21 06:47:50 -070086 return fMode == that.fMode && (kIgnore_Mode == fMode || fDomain == that.fDomain);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000087 }
88
89 /**
joshualittb0a8a372014-09-23 09:50:21 -070090 * A GrGLProcessor subclass that corresponds to a GrProcessor subclass that uses GrTextureDomain
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000091 * should include this helper. It generates the texture domain GLSL, produces the part of the
92 * effect key that reflects the texture domain code, and performs the uniform uploads necessary
93 * for texture domains.
94 */
95 class GLDomain {
96 public:
97 GLDomain() {
joshualittb5fb5af2015-08-25 12:10:54 -070098 for (int i = 0; i < kPrevDomainCount; i++) {
99 fPrevDomain[i] = SK_FloatNaN;
100 }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000101 SkDEBUGCODE(fMode = (Mode) -1;)
102 }
103
104 /**
joshualittb0a8a372014-09-23 09:50:21 -0700105 * Call this from GrGLProcessor::emitCode() to sample the texture W.R.T. the domain and
106 * mode.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000107 *
108 * @param outcolor name of vec4 variable to hold the sampled color.
109 * @param inCoords name of vec2 variable containing the coords to be used with the domain.
110 * It is assumed that this is a variable and not an expression.
111 * @param inModulateColor if non-NULL the sampled color will be modulated with this
112 * expression before being written to outColor.
113 */
114 void sampleTexture(GrGLShaderBuilder* builder,
115 const GrTextureDomain& textureDomain,
116 const char* outColor,
117 const SkString& inCoords,
joshualittb0a8a372014-09-23 09:50:21 -0700118 const GrGLProcessor::TextureSampler sampler,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000119 const char* inModulateColor = NULL);
120
121 /**
joshualittb0a8a372014-09-23 09:50:21 -0700122 * Call this from GrGLProcessor::setData() to upload uniforms necessary for the texture
123 * domain. The rectangle is automatically adjusted to account for the texture's origin.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000124 */
kkinnunen7510b222014-07-30 00:04:16 -0700125 void setData(const GrGLProgramDataManager& pdman, const GrTextureDomain& textureDomain,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000126 GrSurfaceOrigin textureOrigin);
127
128 enum {
129 kDomainKeyBits = 2, // See DomainKey().
130 };
131
132 /**
joshualittb0a8a372014-09-23 09:50:21 -0700133 * GrGLProcessor::GenKey() must call this and include the returned value in it's computed
134 * key. The returned will be limited to the lower kDomainKeyBits bits.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000135 */
bsalomon63e99f72014-07-21 08:03:14 -0700136 static uint32_t DomainKey(const GrTextureDomain& domain) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000137 GR_STATIC_ASSERT(kModeCount <= 4);
138 return domain.mode();
139 }
140
141 private:
joshualittb5fb5af2015-08-25 12:10:54 -0700142 static const int kPrevDomainCount = 4;
kkinnunen7510b222014-07-30 00:04:16 -0700143 SkDEBUGCODE(Mode fMode;)
144 GrGLProgramDataManager::UniformHandle fDomainUni;
145 SkString fDomainName;
joshualittb5fb5af2015-08-25 12:10:54 -0700146 GrGLfloat fPrevDomain[kPrevDomainCount];
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000147 };
148
149protected:
150 Mode fMode;
151 SkRect fDomain;
152 int fIndex;
153
154 typedef GrSingleTextureEffect INHERITED;
155};
156
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000157/**
158 * A basic texture effect that uses GrTextureDomain.
159 */
160class GrTextureDomainEffect : public GrSingleTextureEffect {
161
162public:
joshualitt5f10b5c2015-07-09 10:24:35 -0700163 static GrFragmentProcessor* Create(GrProcessorDataManager*,
164 GrTexture*,
joshualittb0a8a372014-09-23 09:50:21 -0700165 const SkMatrix&,
166 const SkRect& domain,
167 GrTextureDomain::Mode,
168 GrTextureParams::FilterMode filterMode,
169 GrCoordSet = kLocal_GrCoordSet);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000170
171 virtual ~GrTextureDomainEffect();
172
mtklein36352bf2015-03-25 18:17:31 -0700173 const char* name() const override { return "TextureDomain"; }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000174
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000175 const GrTextureDomain& textureDomain() const { return fTextureDomain; }
176
177protected:
178 GrTextureDomain fTextureDomain;
179
180private:
joshualitt5f10b5c2015-07-09 10:24:35 -0700181 GrTextureDomainEffect(GrProcessorDataManager*,
182 GrTexture*,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000183 const SkMatrix&,
184 const SkRect& domain,
185 GrTextureDomain::Mode,
186 GrTextureParams::FilterMode,
187 GrCoordSet);
188
wangyixb1daa862015-08-18 11:29:31 -0700189 GrGLFragmentProcessor* onCreateGLInstance() const override;
190
wangyix4b3050b2015-08-04 07:59:37 -0700191 void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
192
mtklein36352bf2015-03-25 18:17:31 -0700193 bool onIsEqual(const GrFragmentProcessor&) const override;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000194
mtklein36352bf2015-03-25 18:17:31 -0700195 void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
egdaniel1a8ecdf2014-10-03 06:24:12 -0700196
joshualittb0a8a372014-09-23 09:50:21 -0700197 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000198
199 typedef GrSingleTextureEffect INHERITED;
200};
201
202#endif