blob: bbe988cf1b545f7bf393fddc197b6fb56d33c0f6 [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"
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;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000016class GrGLShaderBuilder;
egdaniel605dd0f2014-11-12 08:35:25 -080017class GrInvariantOutput;
egdaniel7dc4bd02015-10-29 07:57:01 -070018class GrGLSLTextureSampler;
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
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000087 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 /**
egdaniel7dc4bd02015-10-29 07:57:01 -070092 * A GrGLFragmentProcessor subclass that corresponds to a GrProcessor subclass that uses
93 * 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 /**
egdaniel7dc4bd02015-10-29 07:57:01 -0700107 * Call this from GrGLFragmentProcessor::emitCode() to sample the texture W.R.T. the domain
108 * 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 */
116 void sampleTexture(GrGLShaderBuilder* builder,
117 const GrTextureDomain& textureDomain,
118 const char* outColor,
119 const SkString& inCoords,
egdaniel7dc4bd02015-10-29 07:57:01 -0700120 const GrGLSLTextureSampler& sampler,
halcanary96fcdcc2015-08-27 07:41:13 -0700121 const char* inModulateColor = nullptr);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000122
123 /**
egdaniel7dc4bd02015-10-29 07:57:01 -0700124 * Call this from GrGLFragmentProcessor::setData() to upload uniforms necessary for the
125 * texture domain. The rectangle is automatically adjusted to account for the texture's
126 * origin.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000127 */
egdaniel018fb622015-10-28 07:26:40 -0700128 void setData(const GrGLSLProgramDataManager& pdman, const GrTextureDomain& textureDomain,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000129 GrSurfaceOrigin textureOrigin);
130
131 enum {
132 kDomainKeyBits = 2, // See DomainKey().
133 };
134
135 /**
egdaniel7dc4bd02015-10-29 07:57:01 -0700136 * GrGLFragmentProcessor::GenKey() must call this and include the returned value in it's
137 * computed key. The returned will be limited to the lower kDomainKeyBits bits.
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000138 */
bsalomon63e99f72014-07-21 08:03:14 -0700139 static uint32_t DomainKey(const GrTextureDomain& domain) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000140 GR_STATIC_ASSERT(kModeCount <= 4);
141 return domain.mode();
142 }
143
144 private:
joshualittb5fb5af2015-08-25 12:10:54 -0700145 static const int kPrevDomainCount = 4;
egdaniel018fb622015-10-28 07:26:40 -0700146 SkDEBUGCODE(Mode fMode;)
147 GrGLSLProgramDataManager::UniformHandle fDomainUni;
148 SkString fDomainName;
149 float fPrevDomain[kPrevDomainCount];
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000150 };
151
152protected:
153 Mode fMode;
154 SkRect fDomain;
155 int fIndex;
156
157 typedef GrSingleTextureEffect INHERITED;
158};
159
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000160/**
161 * A basic texture effect that uses GrTextureDomain.
162 */
163class GrTextureDomainEffect : public GrSingleTextureEffect {
164
165public:
bsalomon0ba8c242015-10-07 09:20:28 -0700166 static const GrFragmentProcessor* Create(GrTexture*,
167 const SkMatrix&,
168 const SkRect& domain,
169 GrTextureDomain::Mode,
170 GrTextureParams::FilterMode filterMode,
171 GrCoordSet = kLocal_GrCoordSet);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000172
173 virtual ~GrTextureDomainEffect();
174
mtklein36352bf2015-03-25 18:17:31 -0700175 const char* name() const override { return "TextureDomain"; }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000176
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000177 const GrTextureDomain& textureDomain() const { return fTextureDomain; }
178
179protected:
180 GrTextureDomain fTextureDomain;
181
182private:
bsalomon4a339522015-10-06 08:40:50 -0700183 GrTextureDomainEffect(GrTexture*,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000184 const SkMatrix&,
185 const SkRect& domain,
186 GrTextureDomain::Mode,
187 GrTextureParams::FilterMode,
188 GrCoordSet);
189
wangyixb1daa862015-08-18 11:29:31 -0700190 GrGLFragmentProcessor* onCreateGLInstance() const override;
191
wangyix4b3050b2015-08-04 07:59:37 -0700192 void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
193
mtklein36352bf2015-03-25 18:17:31 -0700194 bool onIsEqual(const GrFragmentProcessor&) const override;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000195
mtklein36352bf2015-03-25 18:17:31 -0700196 void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
egdaniel1a8ecdf2014-10-03 06:24:12 -0700197
joshualittb0a8a372014-09-23 09:50:21 -0700198 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000199
200 typedef GrSingleTextureEffect INHERITED;
201};
202
203#endif