blob: 891ce10b38d571f754e0aa46faa7490c97efc08c [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"
egdaniel64c47282015-11-13 06:54:19 -080012#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel018fb622015-10-28 07:26:40 -070013#include "glsl/GrGLSLProgramDataManager.h"
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000014
joshualitt30ba4362014-08-21 20:18:45 -070015class GrGLProgramBuilder;
egdaniel2d721d32015-11-11 13:06:05 -080016class GrGLSLShaderBuilder;
egdaniel605dd0f2014-11-12 08:35:25 -080017class GrInvariantOutput;
egdaniel7dc4bd02015-10-29 07:57:01 -070018class GrGLSLTextureSampler;
egdaniel7ea439b2015-12-03 09:20:44 -080019class GrGLSLUniformHandler;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000020struct SkRect;
21
22/**
23 * Limits a texture's lookup coordinates to a domain. Samples outside the domain are either clamped
24 * the edge of the domain or result in a vec4 of zeros (decal mode). The domain is clipped to
25 * normalized texture coords ([0,1]x[0,1] square). Bilinear filtering can cause texels outside the
26 * domain to affect the read value unless the caller considers this when calculating the domain.
27 */
28class GrTextureDomain {
29public:
30 enum Mode {
joshualitt5ae5fc52014-07-29 12:59:27 -070031 // Ignore the texture domain rectangle.
32 kIgnore_Mode,
33 // Clamp texture coords to the domain rectangle.
34 kClamp_Mode,
35 // Treat the area outside the domain rectangle as fully transparent.
36 kDecal_Mode,
37 // Wrap texture coordinates. NOTE: filtering may not work as expected because Bilerp will
38 // read texels outside of the domain. We could perform additional texture reads and filter
39 // in the shader, but are not currently doing this for performance reasons
40 kRepeat_Mode,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000041
joshualitt5ae5fc52014-07-29 12:59:27 -070042 kLastMode = kRepeat_Mode
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000043 };
44 static const int kModeCount = kLastMode + 1;
45
commit-bot@chromium.org7d7f3142013-12-16 15:18:11 +000046 static const GrTextureDomain& IgnoredDomain() {
47 static const SkRect gDummyRect = {0, 0, 0, 0};
48 static const GrTextureDomain gDomain(gDummyRect, kIgnore_Mode);
49 return gDomain;
50 }
51
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000052 /**
53 * @param index Pass a value >= 0 if using multiple texture domains in the same effect.
54 * It is used to keep inserted variables from causing name collisions.
55 */
56 GrTextureDomain(const SkRect& domain, Mode, int index = -1);
57
58 const SkRect& domain() const { return fDomain; }
59 Mode mode() const { return fMode; }
60
61 /* Computes a domain that bounds all the texels in texelRect. Note that with bilerp enabled
62 texels neighboring the domain may be read. */
63 static const SkRect MakeTexelDomain(const GrTexture* texture, const SkIRect& texelRect) {
64 SkScalar wInv = SK_Scalar1 / texture->width();
65 SkScalar hInv = SK_Scalar1 / texture->height();
66 SkRect result = {
67 texelRect.fLeft * wInv,
68 texelRect.fTop * hInv,
69 texelRect.fRight * wInv,
70 texelRect.fBottom * hInv
71 };
72 return result;
73 }
74
senorblancod0d37ca2015-04-02 04:54:56 -070075 static const SkRect MakeTexelDomainForMode(const GrTexture* texture, const SkIRect& texelRect, Mode mode) {
76 // For Clamp mode, inset by half a texel.
77 SkScalar wInv = SK_Scalar1 / texture->width();
78 SkScalar hInv = SK_Scalar1 / texture->height();
79 SkScalar inset = (mode == kClamp_Mode && !texelRect.isEmpty()) ? SK_ScalarHalf : 0;
80 return SkRect::MakeLTRB(
81 (texelRect.fLeft + inset) * wInv,
82 (texelRect.fTop + inset) * hInv,
83 (texelRect.fRight - inset) * wInv,
84 (texelRect.fBottom - inset) * hInv
85 );
86 }
87
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000088 bool operator== (const GrTextureDomain& that) const {
egdaniel01a492f2014-08-21 06:47:50 -070089 return fMode == that.fMode && (kIgnore_Mode == fMode || fDomain == that.fDomain);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000090 }
91
92 /**
egdaniel64c47282015-11-13 06:54:19 -080093 * A GrGLSLFragmentProcessor subclass that corresponds to a GrProcessor subclass that uses
egdaniel7dc4bd02015-10-29 07:57:01 -070094 * GrTextureDomain should include this helper. It generates the texture domain GLSL, produces
95 * the part of the effect key that reflects the texture domain code, and performs the uniform
96 * uploads necessary for texture domains.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000097 */
98 class GLDomain {
99 public:
100 GLDomain() {
joshualittb5fb5af2015-08-25 12:10:54 -0700101 for (int i = 0; i < kPrevDomainCount; i++) {
102 fPrevDomain[i] = SK_FloatNaN;
103 }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000104 SkDEBUGCODE(fMode = (Mode) -1;)
105 }
106
107 /**
egdaniel64c47282015-11-13 06:54:19 -0800108 * Call this from GrGLSLFragmentProcessor::emitCode() to sample the texture W.R.T. the
109 * domain and mode.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000110 *
111 * @param outcolor name of vec4 variable to hold the sampled color.
112 * @param inCoords name of vec2 variable containing the coords to be used with the domain.
113 * It is assumed that this is a variable and not an expression.
halcanary96fcdcc2015-08-27 07:41:13 -0700114 * @param inModulateColor if non-nullptr the sampled color will be modulated with this
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000115 * expression before being written to outColor.
116 */
egdaniel2d721d32015-11-11 13:06:05 -0800117 void sampleTexture(GrGLSLShaderBuilder* builder,
egdaniel7ea439b2015-12-03 09:20:44 -0800118 GrGLSLUniformHandler* uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -0800119 const GrGLSLCaps* glslCaps,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000120 const GrTextureDomain& textureDomain,
121 const char* outColor,
122 const SkString& inCoords,
egdaniel7dc4bd02015-10-29 07:57:01 -0700123 const GrGLSLTextureSampler& sampler,
halcanary96fcdcc2015-08-27 07:41:13 -0700124 const char* inModulateColor = nullptr);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000125
126 /**
egdaniel64c47282015-11-13 06:54:19 -0800127 * Call this from GrGLSLFragmentProcessor::setData() to upload uniforms necessary for the
egdaniel7dc4bd02015-10-29 07:57:01 -0700128 * texture domain. The rectangle is automatically adjusted to account for the texture's
129 * origin.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000130 */
egdaniel018fb622015-10-28 07:26:40 -0700131 void setData(const GrGLSLProgramDataManager& pdman, const GrTextureDomain& textureDomain,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000132 GrSurfaceOrigin textureOrigin);
133
134 enum {
135 kDomainKeyBits = 2, // See DomainKey().
136 };
137
138 /**
egdaniel64c47282015-11-13 06:54:19 -0800139 * GrGLSLFragmentProcessor::GenKey() must call this and include the returned value in it's
egdaniel7dc4bd02015-10-29 07:57:01 -0700140 * computed key. The returned will be limited to the lower kDomainKeyBits bits.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000141 */
bsalomon63e99f72014-07-21 08:03:14 -0700142 static uint32_t DomainKey(const GrTextureDomain& domain) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000143 GR_STATIC_ASSERT(kModeCount <= 4);
144 return domain.mode();
145 }
146
147 private:
joshualittb5fb5af2015-08-25 12:10:54 -0700148 static const int kPrevDomainCount = 4;
egdaniel018fb622015-10-28 07:26:40 -0700149 SkDEBUGCODE(Mode fMode;)
150 GrGLSLProgramDataManager::UniformHandle fDomainUni;
151 SkString fDomainName;
152 float fPrevDomain[kPrevDomainCount];
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000153 };
154
155protected:
156 Mode fMode;
157 SkRect fDomain;
158 int fIndex;
159
160 typedef GrSingleTextureEffect INHERITED;
161};
162
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000163/**
164 * A basic texture effect that uses GrTextureDomain.
165 */
166class GrTextureDomainEffect : public GrSingleTextureEffect {
167
168public:
bsalomon0ba8c242015-10-07 09:20:28 -0700169 static const GrFragmentProcessor* Create(GrTexture*,
170 const SkMatrix&,
171 const SkRect& domain,
172 GrTextureDomain::Mode,
173 GrTextureParams::FilterMode filterMode,
174 GrCoordSet = kLocal_GrCoordSet);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000175
176 virtual ~GrTextureDomainEffect();
177
mtklein36352bf2015-03-25 18:17:31 -0700178 const char* name() const override { return "TextureDomain"; }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000179
robertphillipse004bfc2015-11-16 09:06:59 -0800180 SkString dumpInfo() const override {
181 SkString str;
182 str.appendf("Domain: [L: %.2f, T: %.2f, R: %.2f, B: %.2f] ",
183 fTextureDomain.domain().fLeft, fTextureDomain.domain().fTop,
184 fTextureDomain.domain().fRight, fTextureDomain.domain().fBottom);
185 str.append(INHERITED::dumpInfo());
186 return str;
187 }
188
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000189 const GrTextureDomain& textureDomain() const { return fTextureDomain; }
190
191protected:
192 GrTextureDomain fTextureDomain;
193
194private:
bsalomon4a339522015-10-06 08:40:50 -0700195 GrTextureDomainEffect(GrTexture*,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000196 const SkMatrix&,
197 const SkRect& domain,
198 GrTextureDomain::Mode,
199 GrTextureParams::FilterMode,
200 GrCoordSet);
201
egdaniel57d3b032015-11-13 11:57:27 -0800202 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700203
egdaniel57d3b032015-11-13 11:57:27 -0800204 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700205
mtklein36352bf2015-03-25 18:17:31 -0700206 bool onIsEqual(const GrFragmentProcessor&) const override;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000207
mtklein36352bf2015-03-25 18:17:31 -0700208 void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
egdaniel1a8ecdf2014-10-03 06:24:12 -0700209
joshualittb0a8a372014-09-23 09:50:21 -0700210 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000211
212 typedef GrSingleTextureEffect INHERITED;
213};
214
215#endif