blob: 644d14c7dd94308d2af5f651d279eaf0d50d6428 [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;
egdaniel7ea439b2015-12-03 09:20:44 -080018class GrGLSLUniformHandler;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000019struct SkRect;
20
21/**
22 * Limits a texture's lookup coordinates to a domain. Samples outside the domain are either clamped
23 * the edge of the domain or result in a vec4 of zeros (decal mode). The domain is clipped to
24 * normalized texture coords ([0,1]x[0,1] square). Bilinear filtering can cause texels outside the
25 * domain to affect the read value unless the caller considers this when calculating the domain.
26 */
27class GrTextureDomain {
28public:
29 enum Mode {
joshualitt5ae5fc52014-07-29 12:59:27 -070030 // Ignore the texture domain rectangle.
31 kIgnore_Mode,
32 // Clamp texture coords to the domain rectangle.
33 kClamp_Mode,
34 // Treat the area outside the domain rectangle as fully transparent.
35 kDecal_Mode,
36 // Wrap texture coordinates. NOTE: filtering may not work as expected because Bilerp will
37 // read texels outside of the domain. We could perform additional texture reads and filter
38 // in the shader, but are not currently doing this for performance reasons
39 kRepeat_Mode,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000040
joshualitt5ae5fc52014-07-29 12:59:27 -070041 kLastMode = kRepeat_Mode
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000042 };
43 static const int kModeCount = kLastMode + 1;
44
commit-bot@chromium.org7d7f3142013-12-16 15:18:11 +000045 static const GrTextureDomain& IgnoredDomain() {
46 static const SkRect gDummyRect = {0, 0, 0, 0};
47 static const GrTextureDomain gDomain(gDummyRect, kIgnore_Mode);
48 return gDomain;
49 }
50
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000051 /**
52 * @param index Pass a value >= 0 if using multiple texture domains in the same effect.
53 * It is used to keep inserted variables from causing name collisions.
54 */
55 GrTextureDomain(const SkRect& domain, Mode, int index = -1);
56
57 const SkRect& domain() const { return fDomain; }
58 Mode mode() const { return fMode; }
59
60 /* Computes a domain that bounds all the texels in texelRect. Note that with bilerp enabled
61 texels neighboring the domain may be read. */
62 static const SkRect MakeTexelDomain(const GrTexture* texture, const SkIRect& texelRect) {
63 SkScalar wInv = SK_Scalar1 / texture->width();
64 SkScalar hInv = SK_Scalar1 / texture->height();
65 SkRect result = {
66 texelRect.fLeft * wInv,
67 texelRect.fTop * hInv,
68 texelRect.fRight * wInv,
69 texelRect.fBottom * hInv
70 };
71 return result;
72 }
73
senorblancod0d37ca2015-04-02 04:54:56 -070074 static const SkRect MakeTexelDomainForMode(const GrTexture* texture, const SkIRect& texelRect, Mode mode) {
75 // For Clamp mode, inset by half a texel.
76 SkScalar wInv = SK_Scalar1 / texture->width();
77 SkScalar hInv = SK_Scalar1 / texture->height();
78 SkScalar inset = (mode == kClamp_Mode && !texelRect.isEmpty()) ? SK_ScalarHalf : 0;
79 return SkRect::MakeLTRB(
80 (texelRect.fLeft + inset) * wInv,
81 (texelRect.fTop + inset) * hInv,
82 (texelRect.fRight - inset) * wInv,
83 (texelRect.fBottom - inset) * hInv
84 );
85 }
86
Brian Salomon2ebd0c82016-10-03 17:15:28 -040087 bool operator==(const GrTextureDomain& that) const {
egdaniel01a492f2014-08-21 06:47:50 -070088 return fMode == that.fMode && (kIgnore_Mode == fMode || fDomain == that.fDomain);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000089 }
90
91 /**
egdaniel64c47282015-11-13 06:54:19 -080092 * A GrGLSLFragmentProcessor subclass that corresponds to a GrProcessor subclass that uses
egdaniel7dc4bd02015-10-29 07:57:01 -070093 * GrTextureDomain should include this helper. It generates the texture domain GLSL, produces
94 * the part of the effect key that reflects the texture domain code, and performs the uniform
95 * uploads necessary for texture domains.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000096 */
97 class GLDomain {
98 public:
99 GLDomain() {
joshualittb5fb5af2015-08-25 12:10:54 -0700100 for (int i = 0; i < kPrevDomainCount; i++) {
101 fPrevDomain[i] = SK_FloatNaN;
102 }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000103 SkDEBUGCODE(fMode = (Mode) -1;)
104 }
105
106 /**
egdaniel64c47282015-11-13 06:54:19 -0800107 * Call this from GrGLSLFragmentProcessor::emitCode() to sample the texture W.R.T. the
108 * domain and mode.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000109 *
110 * @param outcolor name of vec4 variable to hold the sampled color.
111 * @param inCoords name of vec2 variable containing the coords to be used with the domain.
112 * It is assumed that this is a variable and not an expression.
halcanary96fcdcc2015-08-27 07:41:13 -0700113 * @param inModulateColor if non-nullptr the sampled color will be modulated with this
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000114 * expression before being written to outColor.
115 */
egdaniel2d721d32015-11-11 13:06:05 -0800116 void sampleTexture(GrGLSLShaderBuilder* builder,
egdaniel7ea439b2015-12-03 09:20:44 -0800117 GrGLSLUniformHandler* uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500118 const GrShaderCaps* shaderCaps,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000119 const GrTextureDomain& textureDomain,
120 const char* outColor,
121 const SkString& inCoords,
egdaniel09aa1fc2016-04-20 07:09:46 -0700122 GrGLSLFragmentProcessor::SamplerHandle sampler,
halcanary96fcdcc2015-08-27 07:41:13 -0700123 const char* inModulateColor = nullptr);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000124
125 /**
egdaniel64c47282015-11-13 06:54:19 -0800126 * Call this from GrGLSLFragmentProcessor::setData() to upload uniforms necessary for the
egdaniel7dc4bd02015-10-29 07:57:01 -0700127 * texture domain. The rectangle is automatically adjusted to account for the texture's
128 * origin.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000129 */
egdaniel018fb622015-10-28 07:26:40 -0700130 void setData(const GrGLSLProgramDataManager& pdman, const GrTextureDomain& textureDomain,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000131 GrSurfaceOrigin textureOrigin);
132
133 enum {
134 kDomainKeyBits = 2, // See DomainKey().
135 };
136
137 /**
egdaniel64c47282015-11-13 06:54:19 -0800138 * GrGLSLFragmentProcessor::GenKey() must call this and include the returned value in it's
egdaniel7dc4bd02015-10-29 07:57:01 -0700139 * computed key. The returned will be limited to the lower kDomainKeyBits bits.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000140 */
bsalomon63e99f72014-07-21 08:03:14 -0700141 static uint32_t DomainKey(const GrTextureDomain& domain) {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400142 GR_STATIC_ASSERT(kModeCount <= (1 << kDomainKeyBits));
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000143 return domain.mode();
144 }
145
146 private:
joshualittb5fb5af2015-08-25 12:10:54 -0700147 static const int kPrevDomainCount = 4;
egdaniel018fb622015-10-28 07:26:40 -0700148 SkDEBUGCODE(Mode fMode;)
149 GrGLSLProgramDataManager::UniformHandle fDomainUni;
150 SkString fDomainName;
151 float fPrevDomain[kPrevDomainCount];
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000152 };
153
154protected:
155 Mode fMode;
156 SkRect fDomain;
157 int fIndex;
158
159 typedef GrSingleTextureEffect INHERITED;
160};
161
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000162/**
163 * A basic texture effect that uses GrTextureDomain.
164 */
165class GrTextureDomainEffect : public GrSingleTextureEffect {
166
167public:
bungeman06ca8ec2016-06-09 08:01:03 -0700168 static sk_sp<GrFragmentProcessor> Make(GrTexture*,
brianosman54f30c12016-07-18 10:53:52 -0700169 sk_sp<GrColorSpaceXform>,
bungeman06ca8ec2016-06-09 08:01:03 -0700170 const SkMatrix&,
171 const SkRect& domain,
172 GrTextureDomain::Mode,
Brian Salomon514baff2016-11-17 15:17:07 -0500173 GrSamplerParams::FilterMode filterMode);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000174
mtklein36352bf2015-03-25 18:17:31 -0700175 const char* name() const override { return "TextureDomain"; }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000176
robertphillipse004bfc2015-11-16 09:06:59 -0800177 SkString dumpInfo() const override {
178 SkString str;
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400179 str.appendf("Domain: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]",
robertphillipse004bfc2015-11-16 09:06:59 -0800180 fTextureDomain.domain().fLeft, fTextureDomain.domain().fTop,
181 fTextureDomain.domain().fRight, fTextureDomain.domain().fBottom);
182 str.append(INHERITED::dumpInfo());
183 return str;
184 }
185
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400186private:
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000187 GrTextureDomain fTextureDomain;
188
bsalomon4a339522015-10-06 08:40:50 -0700189 GrTextureDomainEffect(GrTexture*,
brianosman54f30c12016-07-18 10:53:52 -0700190 sk_sp<GrColorSpaceXform>,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000191 const SkMatrix&,
192 const SkRect& domain,
193 GrTextureDomain::Mode,
Brian Salomon514baff2016-11-17 15:17:07 -0500194 GrSamplerParams::FilterMode);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000195
egdaniel57d3b032015-11-13 11:57:27 -0800196 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700197
Brian Salomon94efbf52016-11-29 13:43:05 -0500198 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700199
mtklein36352bf2015-03-25 18:17:31 -0700200 bool onIsEqual(const GrFragmentProcessor&) const override;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000201
mtklein36352bf2015-03-25 18:17:31 -0700202 void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
egdaniel1a8ecdf2014-10-03 06:24:12 -0700203
joshualittb0a8a372014-09-23 09:50:21 -0700204 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000205
206 typedef GrSingleTextureEffect INHERITED;
207};
208
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400209class GrDeviceSpaceTextureDecalFragmentProcessor : public GrFragmentProcessor {
210public:
211 static sk_sp<GrFragmentProcessor> Make(GrTexture*, const SkIRect& subset,
212 const SkIPoint& deviceSpaceOffset);
213
214 const char* name() const override { return "GrDeviceSpaceTextureDecalFragmentProcessor"; }
215
216 SkString dumpInfo() const override {
217 SkString str;
218 str.appendf("Domain: [L: %.2f, T: %.2f, R: %.2f, B: %.2f] Offset: [%d %d]",
219 fTextureDomain.domain().fLeft, fTextureDomain.domain().fTop,
220 fTextureDomain.domain().fRight, fTextureDomain.domain().fBottom,
221 fDeviceSpaceOffset.fX, fDeviceSpaceOffset.fY);
222 str.append(INHERITED::dumpInfo());
223 return str;
224 }
225
226private:
Brian Salomon0bbecb22016-11-17 11:38:22 -0500227 TextureSampler fTextureSampler;
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400228 GrTextureDomain fTextureDomain;
229 SkIPoint fDeviceSpaceOffset;
230
231 GrDeviceSpaceTextureDecalFragmentProcessor(GrTexture*, const SkIRect&, const SkIPoint&);
232
233 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
234
235 // Since we always use decal mode, there is no need for key data.
Brian Salomon94efbf52016-11-29 13:43:05 -0500236 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400237
238 bool onIsEqual(const GrFragmentProcessor& fp) const override;
239 void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
240
241 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
242
243 typedef GrFragmentProcessor INHERITED;
244};
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000245#endif