blob: 11a9819917d5a6ec3b8c5170a1469ea850b6cf81 [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;
Brian Osmanc4689632016-12-19 17:04:59 -050016class GrGLSLColorSpaceXformHelper;
egdaniel2d721d32015-11-11 13:06:05 -080017class GrGLSLShaderBuilder;
egdaniel605dd0f2014-11-12 08:35:25 -080018class GrInvariantOutput;
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() {
Robert Phillips40fd7c92017-01-30 08:06:27 -050047 static const GrTextureDomain gDomain((GrTextureProxy*)nullptr,
48 SkRect::MakeEmpty(), kIgnore_Mode);
commit-bot@chromium.org7d7f3142013-12-16 15:18:11 +000049 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 */
Robert Phillipse98234f2017-01-09 14:23:59 -050056 GrTextureDomain(GrTexture*, const SkRect& domain, Mode, int index = -1);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000057
Robert Phillips40fd7c92017-01-30 08:06:27 -050058 GrTextureDomain(GrTextureProxy*, const SkRect& domain, Mode, int index = -1);
59
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000060 const SkRect& domain() const { return fDomain; }
61 Mode mode() const { return fMode; }
62
63 /* Computes a domain that bounds all the texels in texelRect. Note that with bilerp enabled
64 texels neighboring the domain may be read. */
Robert Phillipse98234f2017-01-09 14:23:59 -050065 static const SkRect MakeTexelDomain(const SkIRect& texelRect) {
66 return SkRect::Make(texelRect);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000067 }
68
Robert Phillipse98234f2017-01-09 14:23:59 -050069 static const SkRect MakeTexelDomainForMode(const SkIRect& texelRect, Mode mode) {
senorblancod0d37ca2015-04-02 04:54:56 -070070 // For Clamp mode, inset by half a texel.
senorblancod0d37ca2015-04-02 04:54:56 -070071 SkScalar inset = (mode == kClamp_Mode && !texelRect.isEmpty()) ? SK_ScalarHalf : 0;
Robert Phillipse98234f2017-01-09 14:23:59 -050072 return SkRect::MakeLTRB(texelRect.fLeft + inset, texelRect.fTop + inset,
73 texelRect.fRight - inset, texelRect.fBottom - inset);
senorblancod0d37ca2015-04-02 04:54:56 -070074 }
75
Brian Salomon2ebd0c82016-10-03 17:15:28 -040076 bool operator==(const GrTextureDomain& that) const {
egdaniel01a492f2014-08-21 06:47:50 -070077 return fMode == that.fMode && (kIgnore_Mode == fMode || fDomain == that.fDomain);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000078 }
79
80 /**
egdaniel64c47282015-11-13 06:54:19 -080081 * A GrGLSLFragmentProcessor subclass that corresponds to a GrProcessor subclass that uses
egdaniel7dc4bd02015-10-29 07:57:01 -070082 * GrTextureDomain should include this helper. It generates the texture domain GLSL, produces
83 * the part of the effect key that reflects the texture domain code, and performs the uniform
84 * uploads necessary for texture domains.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000085 */
86 class GLDomain {
87 public:
88 GLDomain() {
joshualittb5fb5af2015-08-25 12:10:54 -070089 for (int i = 0; i < kPrevDomainCount; i++) {
90 fPrevDomain[i] = SK_FloatNaN;
91 }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000092 SkDEBUGCODE(fMode = (Mode) -1;)
93 }
94
95 /**
egdaniel64c47282015-11-13 06:54:19 -080096 * Call this from GrGLSLFragmentProcessor::emitCode() to sample the texture W.R.T. the
97 * domain and mode.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000098 *
99 * @param outcolor name of vec4 variable to hold the sampled color.
100 * @param inCoords name of vec2 variable containing the coords to be used with the domain.
101 * It is assumed that this is a variable and not an expression.
halcanary96fcdcc2015-08-27 07:41:13 -0700102 * @param inModulateColor if non-nullptr the sampled color will be modulated with this
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000103 * expression before being written to outColor.
104 */
egdaniel2d721d32015-11-11 13:06:05 -0800105 void sampleTexture(GrGLSLShaderBuilder* builder,
egdaniel7ea439b2015-12-03 09:20:44 -0800106 GrGLSLUniformHandler* uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500107 const GrShaderCaps* shaderCaps,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000108 const GrTextureDomain& textureDomain,
109 const char* outColor,
110 const SkString& inCoords,
egdaniel09aa1fc2016-04-20 07:09:46 -0700111 GrGLSLFragmentProcessor::SamplerHandle sampler,
Brian Osmanc4689632016-12-19 17:04:59 -0500112 const char* inModulateColor = nullptr,
113 GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000114
115 /**
egdaniel64c47282015-11-13 06:54:19 -0800116 * Call this from GrGLSLFragmentProcessor::setData() to upload uniforms necessary for the
egdaniel7dc4bd02015-10-29 07:57:01 -0700117 * texture domain. The rectangle is automatically adjusted to account for the texture's
118 * origin.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000119 */
egdaniel018fb622015-10-28 07:26:40 -0700120 void setData(const GrGLSLProgramDataManager& pdman, const GrTextureDomain& textureDomain,
Robert Phillipse98234f2017-01-09 14:23:59 -0500121 GrTexture* texure);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000122
123 enum {
124 kDomainKeyBits = 2, // See DomainKey().
125 };
126
127 /**
egdaniel64c47282015-11-13 06:54:19 -0800128 * GrGLSLFragmentProcessor::GenKey() must call this and include the returned value in it's
egdaniel7dc4bd02015-10-29 07:57:01 -0700129 * computed key. The returned will be limited to the lower kDomainKeyBits bits.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000130 */
bsalomon63e99f72014-07-21 08:03:14 -0700131 static uint32_t DomainKey(const GrTextureDomain& domain) {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400132 GR_STATIC_ASSERT(kModeCount <= (1 << kDomainKeyBits));
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000133 return domain.mode();
134 }
135
136 private:
joshualittb5fb5af2015-08-25 12:10:54 -0700137 static const int kPrevDomainCount = 4;
egdaniel018fb622015-10-28 07:26:40 -0700138 SkDEBUGCODE(Mode fMode;)
139 GrGLSLProgramDataManager::UniformHandle fDomainUni;
140 SkString fDomainName;
141 float fPrevDomain[kPrevDomainCount];
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000142 };
143
144protected:
145 Mode fMode;
146 SkRect fDomain;
147 int fIndex;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000148};
149
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000150/**
151 * A basic texture effect that uses GrTextureDomain.
152 */
153class GrTextureDomainEffect : public GrSingleTextureEffect {
154
155public:
bungeman06ca8ec2016-06-09 08:01:03 -0700156 static sk_sp<GrFragmentProcessor> Make(GrTexture*,
brianosman54f30c12016-07-18 10:53:52 -0700157 sk_sp<GrColorSpaceXform>,
bungeman06ca8ec2016-06-09 08:01:03 -0700158 const SkMatrix&,
159 const SkRect& domain,
160 GrTextureDomain::Mode,
Brian Salomon514baff2016-11-17 15:17:07 -0500161 GrSamplerParams::FilterMode filterMode);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000162
Robert Phillips296b1cc2017-03-15 10:42:12 -0400163 static sk_sp<GrFragmentProcessor> Make(GrResourceProvider*,
Robert Phillips40fd7c92017-01-30 08:06:27 -0500164 sk_sp<GrTextureProxy>,
165 sk_sp<GrColorSpaceXform>,
166 const SkMatrix&,
167 const SkRect& domain,
168 GrTextureDomain::Mode,
169 GrSamplerParams::FilterMode filterMode);
170
mtklein36352bf2015-03-25 18:17:31 -0700171 const char* name() const override { return "TextureDomain"; }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000172
robertphillipse004bfc2015-11-16 09:06:59 -0800173 SkString dumpInfo() const override {
174 SkString str;
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400175 str.appendf("Domain: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]",
robertphillipse004bfc2015-11-16 09:06:59 -0800176 fTextureDomain.domain().fLeft, fTextureDomain.domain().fTop,
177 fTextureDomain.domain().fRight, fTextureDomain.domain().fBottom);
178 str.append(INHERITED::dumpInfo());
179 return str;
180 }
181
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400182private:
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000183 GrTextureDomain fTextureDomain;
184
bsalomon4a339522015-10-06 08:40:50 -0700185 GrTextureDomainEffect(GrTexture*,
brianosman54f30c12016-07-18 10:53:52 -0700186 sk_sp<GrColorSpaceXform>,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000187 const SkMatrix&,
188 const SkRect& domain,
189 GrTextureDomain::Mode,
Brian Salomon514baff2016-11-17 15:17:07 -0500190 GrSamplerParams::FilterMode);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000191
Robert Phillips296b1cc2017-03-15 10:42:12 -0400192 GrTextureDomainEffect(GrResourceProvider*,
Robert Phillips40fd7c92017-01-30 08:06:27 -0500193 sk_sp<GrTextureProxy>,
194 sk_sp<GrColorSpaceXform>,
195 const SkMatrix&,
196 const SkRect& domain,
197 GrTextureDomain::Mode,
198 GrSamplerParams::FilterMode);
199
200 static OptimizationFlags OptFlags(GrPixelConfig config, GrTextureDomain::Mode mode);
Brian Salomon587e08f2017-01-27 10:59:27 -0500201
egdaniel57d3b032015-11-13 11:57:27 -0800202 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700203
Brian Salomon94efbf52016-11-29 13:43:05 -0500204 void onGetGLSLProcessorKey(const GrShaderCaps&, 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
joshualittb0a8a372014-09-23 09:50:21 -0700208 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000209
210 typedef GrSingleTextureEffect INHERITED;
211};
212
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400213class GrDeviceSpaceTextureDecalFragmentProcessor : public GrFragmentProcessor {
214public:
215 static sk_sp<GrFragmentProcessor> Make(GrTexture*, const SkIRect& subset,
216 const SkIPoint& deviceSpaceOffset);
217
Robert Phillips296b1cc2017-03-15 10:42:12 -0400218 static sk_sp<GrFragmentProcessor> Make(GrResourceProvider*, sk_sp<GrTextureProxy>,
219 const SkIRect& subset,
Robert Phillips40fd7c92017-01-30 08:06:27 -0500220 const SkIPoint& deviceSpaceOffset);
221
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400222 const char* name() const override { return "GrDeviceSpaceTextureDecalFragmentProcessor"; }
223
224 SkString dumpInfo() const override {
225 SkString str;
226 str.appendf("Domain: [L: %.2f, T: %.2f, R: %.2f, B: %.2f] Offset: [%d %d]",
227 fTextureDomain.domain().fLeft, fTextureDomain.domain().fTop,
228 fTextureDomain.domain().fRight, fTextureDomain.domain().fBottom,
229 fDeviceSpaceOffset.fX, fDeviceSpaceOffset.fY);
230 str.append(INHERITED::dumpInfo());
231 return str;
232 }
233
234private:
Brian Salomon0bbecb22016-11-17 11:38:22 -0500235 TextureSampler fTextureSampler;
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400236 GrTextureDomain fTextureDomain;
237 SkIPoint fDeviceSpaceOffset;
238
239 GrDeviceSpaceTextureDecalFragmentProcessor(GrTexture*, const SkIRect&, const SkIPoint&);
240
Robert Phillips296b1cc2017-03-15 10:42:12 -0400241 GrDeviceSpaceTextureDecalFragmentProcessor(GrResourceProvider*, sk_sp<GrTextureProxy>,
Robert Phillips40fd7c92017-01-30 08:06:27 -0500242 const SkIRect&, const SkIPoint&);
243
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400244 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
245
246 // Since we always use decal mode, there is no need for key data.
Brian Salomon94efbf52016-11-29 13:43:05 -0500247 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400248
249 bool onIsEqual(const GrFragmentProcessor& fp) const override;
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400250
251 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
252
253 typedef GrFragmentProcessor INHERITED;
254};
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000255#endif