blob: 0db7d2c202bcf8fb87bf46271bbe5868a23335bc [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
Brian Salomon6cd51b52017-07-26 19:07:15 -040011#include "GrCoordTransform.h"
12#include "GrFragmentProcessor.h"
13#include "GrColorSpaceXform.h"
egdaniel64c47282015-11-13 06:54:19 -080014#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel018fb622015-10-28 07:26:40 -070015#include "glsl/GrGLSLProgramDataManager.h"
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000016
joshualitt30ba4362014-08-21 20:18:45 -070017class GrGLProgramBuilder;
Brian Osmanc4689632016-12-19 17:04:59 -050018class GrGLSLColorSpaceXformHelper;
egdaniel2d721d32015-11-11 13:06:05 -080019class GrGLSLShaderBuilder;
egdaniel605dd0f2014-11-12 08:35:25 -080020class GrInvariantOutput;
egdaniel7ea439b2015-12-03 09:20:44 -080021class GrGLSLUniformHandler;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000022struct SkRect;
23
24/**
25 * Limits a texture's lookup coordinates to a domain. Samples outside the domain are either clamped
Ethan Nicholas5af9ea32017-07-28 15:19:46 -040026 * the edge of the domain or result in a float4 of zeros (decal mode). The domain is clipped to
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000027 * normalized texture coords ([0,1]x[0,1] square). Bilinear filtering can cause texels outside the
28 * domain to affect the read value unless the caller considers this when calculating the domain.
29 */
30class GrTextureDomain {
31public:
32 enum Mode {
joshualitt5ae5fc52014-07-29 12:59:27 -070033 // Ignore the texture domain rectangle.
34 kIgnore_Mode,
35 // Clamp texture coords to the domain rectangle.
36 kClamp_Mode,
37 // Treat the area outside the domain rectangle as fully transparent.
38 kDecal_Mode,
39 // Wrap texture coordinates. NOTE: filtering may not work as expected because Bilerp will
40 // read texels outside of the domain. We could perform additional texture reads and filter
41 // in the shader, but are not currently doing this for performance reasons
42 kRepeat_Mode,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000043
joshualitt5ae5fc52014-07-29 12:59:27 -070044 kLastMode = kRepeat_Mode
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000045 };
46 static const int kModeCount = kLastMode + 1;
47
commit-bot@chromium.org7d7f3142013-12-16 15:18:11 +000048 static const GrTextureDomain& IgnoredDomain() {
Robert Phillips40fd7c92017-01-30 08:06:27 -050049 static const GrTextureDomain gDomain((GrTextureProxy*)nullptr,
50 SkRect::MakeEmpty(), kIgnore_Mode);
commit-bot@chromium.org7d7f3142013-12-16 15:18:11 +000051 return gDomain;
52 }
53
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000054 /**
55 * @param index Pass a value >= 0 if using multiple texture domains in the same effect.
56 * It is used to keep inserted variables from causing name collisions.
57 */
Robert Phillips40fd7c92017-01-30 08:06:27 -050058 GrTextureDomain(GrTextureProxy*, const SkRect& domain, Mode, int index = -1);
59
Brian Salomonffc2ec42017-07-25 14:59:03 -040060 GrTextureDomain(const GrTextureDomain&) = default;
61
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000062 const SkRect& domain() const { return fDomain; }
63 Mode mode() const { return fMode; }
64
65 /* Computes a domain that bounds all the texels in texelRect. Note that with bilerp enabled
66 texels neighboring the domain may be read. */
Robert Phillipse98234f2017-01-09 14:23:59 -050067 static const SkRect MakeTexelDomain(const SkIRect& texelRect) {
68 return SkRect::Make(texelRect);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000069 }
70
Robert Phillipse98234f2017-01-09 14:23:59 -050071 static const SkRect MakeTexelDomainForMode(const SkIRect& texelRect, Mode mode) {
senorblancod0d37ca2015-04-02 04:54:56 -070072 // For Clamp mode, inset by half a texel.
senorblancod0d37ca2015-04-02 04:54:56 -070073 SkScalar inset = (mode == kClamp_Mode && !texelRect.isEmpty()) ? SK_ScalarHalf : 0;
Robert Phillipse98234f2017-01-09 14:23:59 -050074 return SkRect::MakeLTRB(texelRect.fLeft + inset, texelRect.fTop + inset,
75 texelRect.fRight - inset, texelRect.fBottom - inset);
senorblancod0d37ca2015-04-02 04:54:56 -070076 }
77
Brian Salomon2ebd0c82016-10-03 17:15:28 -040078 bool operator==(const GrTextureDomain& that) const {
egdaniel01a492f2014-08-21 06:47:50 -070079 return fMode == that.fMode && (kIgnore_Mode == fMode || fDomain == that.fDomain);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000080 }
81
82 /**
egdaniel64c47282015-11-13 06:54:19 -080083 * A GrGLSLFragmentProcessor subclass that corresponds to a GrProcessor subclass that uses
egdaniel7dc4bd02015-10-29 07:57:01 -070084 * GrTextureDomain should include this helper. It generates the texture domain GLSL, produces
85 * the part of the effect key that reflects the texture domain code, and performs the uniform
86 * uploads necessary for texture domains.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000087 */
88 class GLDomain {
89 public:
90 GLDomain() {
joshualittb5fb5af2015-08-25 12:10:54 -070091 for (int i = 0; i < kPrevDomainCount; i++) {
92 fPrevDomain[i] = SK_FloatNaN;
93 }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000094 SkDEBUGCODE(fMode = (Mode) -1;)
95 }
96
97 /**
egdaniel64c47282015-11-13 06:54:19 -080098 * Call this from GrGLSLFragmentProcessor::emitCode() to sample the texture W.R.T. the
99 * domain and mode.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000100 *
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400101 * @param outcolor name of float4 variable to hold the sampled color.
102 * @param inCoords name of float2 variable containing the coords to be used with the domain.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000103 * It is assumed that this is a variable and not an expression.
halcanary96fcdcc2015-08-27 07:41:13 -0700104 * @param inModulateColor if non-nullptr the sampled color will be modulated with this
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000105 * expression before being written to outColor.
106 */
egdaniel2d721d32015-11-11 13:06:05 -0800107 void sampleTexture(GrGLSLShaderBuilder* builder,
egdaniel7ea439b2015-12-03 09:20:44 -0800108 GrGLSLUniformHandler* uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500109 const GrShaderCaps* shaderCaps,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000110 const GrTextureDomain& textureDomain,
111 const char* outColor,
112 const SkString& inCoords,
egdaniel09aa1fc2016-04-20 07:09:46 -0700113 GrGLSLFragmentProcessor::SamplerHandle sampler,
Brian Osmanc4689632016-12-19 17:04:59 -0500114 const char* inModulateColor = nullptr,
115 GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000116
117 /**
egdaniel64c47282015-11-13 06:54:19 -0800118 * Call this from GrGLSLFragmentProcessor::setData() to upload uniforms necessary for the
egdaniel7dc4bd02015-10-29 07:57:01 -0700119 * texture domain. The rectangle is automatically adjusted to account for the texture's
120 * origin.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000121 */
Robert Phillipsc686ce32017-07-21 14:12:29 -0400122 void setData(const GrGLSLProgramDataManager&, const GrTextureDomain&, GrSurfaceProxy*);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000123
124 enum {
125 kDomainKeyBits = 2, // See DomainKey().
126 };
127
128 /**
egdaniel64c47282015-11-13 06:54:19 -0800129 * GrGLSLFragmentProcessor::GenKey() must call this and include the returned value in it's
egdaniel7dc4bd02015-10-29 07:57:01 -0700130 * computed key. The returned will be limited to the lower kDomainKeyBits bits.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000131 */
bsalomon63e99f72014-07-21 08:03:14 -0700132 static uint32_t DomainKey(const GrTextureDomain& domain) {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400133 GR_STATIC_ASSERT(kModeCount <= (1 << kDomainKeyBits));
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000134 return domain.mode();
135 }
136
137 private:
joshualittb5fb5af2015-08-25 12:10:54 -0700138 static const int kPrevDomainCount = 4;
egdaniel018fb622015-10-28 07:26:40 -0700139 SkDEBUGCODE(Mode fMode;)
140 GrGLSLProgramDataManager::UniformHandle fDomainUni;
141 SkString fDomainName;
142 float fPrevDomain[kPrevDomainCount];
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000143 };
144
145protected:
146 Mode fMode;
147 SkRect fDomain;
148 int fIndex;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000149};
150
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000151/**
152 * A basic texture effect that uses GrTextureDomain.
153 */
Brian Salomon6cd51b52017-07-26 19:07:15 -0400154class GrTextureDomainEffect : public GrFragmentProcessor {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000155public:
Brian Salomonaff329b2017-08-11 09:40:37 -0400156 static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy>,
157 sk_sp<GrColorSpaceXform>,
158 const SkMatrix&,
159 const SkRect& domain,
160 GrTextureDomain::Mode,
161 GrSamplerParams::FilterMode filterMode);
Robert Phillips40fd7c92017-01-30 08:06:27 -0500162
mtklein36352bf2015-03-25 18:17:31 -0700163 const char* name() const override { return "TextureDomain"; }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000164
Brian Salomonaff329b2017-08-11 09:40:37 -0400165 std::unique_ptr<GrFragmentProcessor> clone() const override {
166 return std::unique_ptr<GrFragmentProcessor>(new GrTextureDomainEffect(*this));
Brian Salomon3f6f9652017-07-28 07:34:05 -0400167 }
168
robertphillipse004bfc2015-11-16 09:06:59 -0800169 SkString dumpInfo() const override {
170 SkString str;
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400171 str.appendf("Domain: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]",
robertphillipse004bfc2015-11-16 09:06:59 -0800172 fTextureDomain.domain().fLeft, fTextureDomain.domain().fTop,
173 fTextureDomain.domain().fRight, fTextureDomain.domain().fBottom);
174 str.append(INHERITED::dumpInfo());
175 return str;
176 }
177
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400178private:
Brian Salomon6cd51b52017-07-26 19:07:15 -0400179 GrCoordTransform fCoordTransform;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000180 GrTextureDomain fTextureDomain;
Brian Salomon6cd51b52017-07-26 19:07:15 -0400181 TextureSampler fTextureSampler;
182 sk_sp<GrColorSpaceXform> fColorSpaceXform;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000183
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400184 GrTextureDomainEffect(sk_sp<GrTextureProxy>,
Robert Phillips40fd7c92017-01-30 08:06:27 -0500185 sk_sp<GrColorSpaceXform>,
186 const SkMatrix&,
187 const SkRect& domain,
188 GrTextureDomain::Mode,
189 GrSamplerParams::FilterMode);
190
Brian Salomon3f6f9652017-07-28 07:34:05 -0400191 explicit GrTextureDomainEffect(const GrTextureDomainEffect&);
192
Robert Phillips40fd7c92017-01-30 08:06:27 -0500193 static OptimizationFlags OptFlags(GrPixelConfig config, GrTextureDomain::Mode mode);
Brian Salomon587e08f2017-01-27 10:59:27 -0500194
egdaniel57d3b032015-11-13 11:57:27 -0800195 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700196
Brian Salomon94efbf52016-11-29 13:43:05 -0500197 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700198
mtklein36352bf2015-03-25 18:17:31 -0700199 bool onIsEqual(const GrFragmentProcessor&) const override;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000200
Brian Salomon6cd51b52017-07-26 19:07:15 -0400201 const GrColorSpaceXform* colorSpaceXform() const { return fColorSpaceXform.get(); }
202
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400203 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000204
Brian Salomon6cd51b52017-07-26 19:07:15 -0400205 typedef GrFragmentProcessor INHERITED;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000206};
207
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400208class GrDeviceSpaceTextureDecalFragmentProcessor : public GrFragmentProcessor {
209public:
Brian Salomonaff329b2017-08-11 09:40:37 -0400210 static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy>,
211 const SkIRect& subset,
212 const SkIPoint& deviceSpaceOffset);
Robert Phillips40fd7c92017-01-30 08:06:27 -0500213
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400214 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
Brian Salomonaff329b2017-08-11 09:40:37 -0400226 std::unique_ptr<GrFragmentProcessor> clone() const override;
Brian Salomon1a2a7ab2017-07-26 13:11:51 -0400227
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400228private:
Brian Salomon0bbecb22016-11-17 11:38:22 -0500229 TextureSampler fTextureSampler;
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400230 GrTextureDomain fTextureDomain;
231 SkIPoint fDeviceSpaceOffset;
232
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400233 GrDeviceSpaceTextureDecalFragmentProcessor(sk_sp<GrTextureProxy>,
Robert Phillips40fd7c92017-01-30 08:06:27 -0500234 const SkIRect&, const SkIPoint&);
Brian Salomon1a2a7ab2017-07-26 13:11:51 -0400235 GrDeviceSpaceTextureDecalFragmentProcessor(const GrDeviceSpaceTextureDecalFragmentProcessor&);
Robert Phillips40fd7c92017-01-30 08:06:27 -0500236
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400237 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
238
239 // Since we always use decal mode, there is no need for key data.
Brian Salomon94efbf52016-11-29 13:43:05 -0500240 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400241
242 bool onIsEqual(const GrFragmentProcessor& fp) const override;
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400243
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400244 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400245
246 typedef GrFragmentProcessor INHERITED;
247};
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000248#endif