blob: 80907feec3d1f4bb5ddef1118bf2b01ab87b1c8e [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/effects/GrTextureDomain.h"
Robert Phillips40fd7c92017-01-30 08:06:27 -05009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/gpu/GrTexture.h"
11#include "include/private/SkFloatingPoint.h"
12#include "src/gpu/GrProxyProvider.h"
13#include "src/gpu/GrShaderCaps.h"
14#include "src/gpu/GrSurfaceProxyPriv.h"
15#include "src/gpu/effects/generated/GrSimpleTextureEffect.h"
16#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
17#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
18#include "src/gpu/glsl/GrGLSLProgramDataManager.h"
19#include "src/gpu/glsl/GrGLSLShaderBuilder.h"
20#include "src/gpu/glsl/GrGLSLUniformHandler.h"
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000021
Ben Wagnerf08d1d02018-06-18 15:11:00 -040022#include <utility>
23
Michael Ludwig8fa469d2019-11-25 16:08:44 -050024GrTextureDomain::GrTextureDomain(GrSurfaceProxy* proxy, const SkRect& domain, Mode modeX,
Michael Ludwigbe315a22018-12-17 09:50:51 -050025 Mode modeY, int index)
26 : fModeX(modeX)
27 , fModeY(modeY)
Robert Phillips40fd7c92017-01-30 08:06:27 -050028 , fIndex(index) {
29
Michael Ludwigbe315a22018-12-17 09:50:51 -050030 if (!proxy) {
31 SkASSERT(modeX == kIgnore_Mode && modeY == kIgnore_Mode);
Robert Phillips40fd7c92017-01-30 08:06:27 -050032 return;
33 }
34
Brian Salomon9f2b86c2019-10-22 10:37:46 -040035 const SkRect kFullRect = proxy->getBoundsRect();
Robert Phillips40fd7c92017-01-30 08:06:27 -050036
37 // We don't currently handle domains that are empty or don't intersect the texture.
38 // It is OK if the domain rect is a line or point, but it should not be inverted. We do not
39 // handle rects that do not intersect the [0..1]x[0..1] rect.
Michael Ludwig170de012019-11-15 21:55:18 +000040 SkASSERT(domain.fLeft <= domain.fRight);
41 SkASSERT(domain.fTop <= domain.fBottom);
Robert Phillips40fd7c92017-01-30 08:06:27 -050042 fDomain.fLeft = SkScalarPin(domain.fLeft, 0.0f, kFullRect.fRight);
43 fDomain.fRight = SkScalarPin(domain.fRight, fDomain.fLeft, kFullRect.fRight);
44 fDomain.fTop = SkScalarPin(domain.fTop, 0.0f, kFullRect.fBottom);
45 fDomain.fBottom = SkScalarPin(domain.fBottom, fDomain.fTop, kFullRect.fBottom);
46 SkASSERT(fDomain.fLeft <= fDomain.fRight);
47 SkASSERT(fDomain.fTop <= fDomain.fBottom);
48}
49
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000050//////////////////////////////////////////////////////////////////////////////
51
Michael Ludwigbe315a22018-12-17 09:50:51 -050052static SkString clamp_expression(GrTextureDomain::Mode mode, const char* inCoord,
53 const char* coordSwizzle, const char* domain,
54 const char* minSwizzle, const char* maxSwizzle) {
55 SkString clampedExpr;
56 switch(mode) {
57 case GrTextureDomain::kIgnore_Mode:
58 clampedExpr.printf("%s.%s\n", inCoord, coordSwizzle);
59 break;
60 case GrTextureDomain::kDecal_Mode:
61 // The lookup coordinate to use for decal will be clamped just like kClamp_Mode,
62 // it's just that the post-processing will be different, so fall through
63 case GrTextureDomain::kClamp_Mode:
64 clampedExpr.printf("clamp(%s.%s, %s.%s, %s.%s)",
65 inCoord, coordSwizzle, domain, minSwizzle, domain, maxSwizzle);
66 break;
67 case GrTextureDomain::kRepeat_Mode:
68 clampedExpr.printf("mod(%s.%s - %s.%s, %s.%s - %s.%s) + %s.%s",
69 inCoord, coordSwizzle, domain, minSwizzle, domain, maxSwizzle,
70 domain, minSwizzle, domain, minSwizzle);
71 break;
72 default:
73 SkASSERTF(false, "Unknown texture domain mode: %u\n", (uint32_t) mode);
74 break;
75 }
76 return clampedExpr;
77}
78
egdaniel2d721d32015-11-11 13:06:05 -080079void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
egdaniel7ea439b2015-12-03 09:20:44 -080080 GrGLSLUniformHandler* uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -050081 const GrShaderCaps* shaderCaps,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000082 const GrTextureDomain& textureDomain,
83 const char* outColor,
84 const SkString& inCoords,
egdaniel09aa1fc2016-04-20 07:09:46 -070085 GrGLSLFragmentProcessor::SamplerHandle sampler,
Brian Osman2240be92017-10-18 13:15:13 -040086 const char* inModulateColor) {
Michael Ludwigbe315a22018-12-17 09:50:51 -050087 SkASSERT(!fHasMode || (textureDomain.modeX() == fModeX && textureDomain.modeY() == fModeY));
88 SkDEBUGCODE(fModeX = textureDomain.modeX();)
89 SkDEBUGCODE(fModeY = textureDomain.modeY();)
Hans Wennborgc63ec5c2017-12-08 18:56:23 -080090 SkDEBUGCODE(fHasMode = true;)
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000091
Michael Ludwigbe315a22018-12-17 09:50:51 -050092 if ((textureDomain.modeX() != kIgnore_Mode || textureDomain.modeY() != kIgnore_Mode) &&
93 !fDomainUni.isValid()) {
94 // Must include the domain uniform since at least one axis uses it
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000095 const char* name;
96 SkString uniName("TexDom");
97 if (textureDomain.fIndex >= 0) {
98 uniName.appendS32(textureDomain.fIndex);
99 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400100 fDomainUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
egdaniel7ea439b2015-12-03 09:20:44 -0800101 uniName.c_str(), &name);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000102 fDomainName = name;
103 }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000104
Michael Ludwigbe315a22018-12-17 09:50:51 -0500105 bool decalX = textureDomain.modeX() == kDecal_Mode;
106 bool decalY = textureDomain.modeY() == kDecal_Mode;
107 if ((decalX || decalY) && !fDecalUni.isValid()) {
108 const char* name;
109 SkString uniName("DecalParams");
110 if (textureDomain.fIndex >= 0) {
111 uniName.appendS32(textureDomain.fIndex);
joshualitt5ae5fc52014-07-29 12:59:27 -0700112 }
Michael Ludwigbe315a22018-12-17 09:50:51 -0500113 // Half3 since this will hold texture width, height, and then a step function control param
114 fDecalUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
115 uniName.c_str(), &name);
116 fDecalName = name;
117 }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000118
Michael Ludwigbe315a22018-12-17 09:50:51 -0500119 // Add a block so that we can declare variables
120 GrGLSLShaderBuilder::ShaderBlock block(builder);
121 // Always use a local variable for the input coordinates; often callers pass in an expression
122 // and we want to cache it across all of its references in the code below
123 builder->codeAppendf("float2 origCoord = %s;", inCoords.c_str());
124 builder->codeAppend("float2 clampedCoord = ");
125 if (textureDomain.modeX() != textureDomain.modeY()) {
126 // The wrap modes differ on the two axes, so build up a coordinate that respects each axis'
127 // domain rule independently before sampling the texture.
128 SkString tcX = clamp_expression(textureDomain.modeX(), "origCoord", "x",
129 fDomainName.c_str(), "x", "z");
130 SkString tcY = clamp_expression(textureDomain.modeY(), "origCoord", "y",
131 fDomainName.c_str(), "y", "w");
132 builder->codeAppendf("float2(%s, %s)", tcX.c_str(), tcY.c_str());
133 } else {
134 // Since the x and y axis wrap modes are the same, they can be calculated together using
135 // more efficient vector operations
136 SkString tc = clamp_expression(textureDomain.modeX(), "origCoord", "xy",
137 fDomainName.c_str(), "xy", "zw");
138 builder->codeAppend(tc.c_str());
139 }
140 builder->codeAppend(";");
141
Michael Ludwig170de012019-11-15 21:55:18 +0000142 // Look up the texture sample at the clamped coordinate location
143 builder->codeAppend("half4 inside = ");
144 builder->appendTextureLookupAndModulate(inModulateColor, sampler, "clampedCoord",
145 kFloat2_GrSLType);
146 builder->codeAppend(";");
Michael Ludwigbe315a22018-12-17 09:50:51 -0500147
148 // Apply decal mode's transparency interpolation if needed
149 if (decalX || decalY) {
150 // The decal err is the max absoluate value between the clamped coordinate and the original
151 // pixel coordinate. This will then be clamped to 1.f if it's greater than the control
152 // parameter, which simulates kNearest and kBilerp behavior depending on if it's 0 or 1.
153 if (decalX && decalY) {
Ethan Nicholase1f55022019-02-05 17:17:40 -0500154 builder->codeAppendf("half err = max(half(abs(clampedCoord.x - origCoord.x) * %s.x), "
155 "half(abs(clampedCoord.y - origCoord.y) * %s.y));",
Michael Ludwigbe315a22018-12-17 09:50:51 -0500156 fDecalName.c_str(), fDecalName.c_str());
157 } else if (decalX) {
Ethan Nicholase1f55022019-02-05 17:17:40 -0500158 builder->codeAppendf("half err = half(abs(clampedCoord.x - origCoord.x) * %s.x);",
Michael Ludwigbe315a22018-12-17 09:50:51 -0500159 fDecalName.c_str());
160 } else {
161 SkASSERT(decalY);
Ethan Nicholase1f55022019-02-05 17:17:40 -0500162 builder->codeAppendf("half err = half(abs(clampedCoord.y - origCoord.y) * %s.y);",
Michael Ludwigbe315a22018-12-17 09:50:51 -0500163 fDecalName.c_str());
joshualitt5ae5fc52014-07-29 12:59:27 -0700164 }
joshualitt5ae5fc52014-07-29 12:59:27 -0700165
Michael Ludwigbe315a22018-12-17 09:50:51 -0500166 // Apply a transform to the error rate, which let's us simulate nearest or bilerp filtering
167 // in the same shader. When the texture is nearest filtered, fSizeName.z is set to 1/2 so
168 // this becomes a step function centered at .5 away from the clamped coordinate (but the
169 // domain for decal is inset by .5 so the edge lines up properly). When bilerp, fSizeName.z
170 // is set to 1 and it becomes a simple linear blend between texture and transparent.
171 builder->codeAppendf("if (err > %s.z) { err = 1.0; } else if (%s.z < 1) { err = 0.0; }",
172 fDecalName.c_str(), fDecalName.c_str());
Michael Ludwig170de012019-11-15 21:55:18 +0000173 builder->codeAppendf("%s = mix(inside, half4(0, 0, 0, 0), err);", outColor);
Michael Ludwigbe315a22018-12-17 09:50:51 -0500174 } else {
175 // A simple look up
Michael Ludwig170de012019-11-15 21:55:18 +0000176 builder->codeAppendf("%s = inside;", outColor);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000177 }
178}
179
egdaniel018fb622015-10-28 07:26:40 -0700180void GrTextureDomain::GLDomain::setData(const GrGLSLProgramDataManager& pdman,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000181 const GrTextureDomain& textureDomain,
Michael Ludwig8fa469d2019-11-25 16:08:44 -0500182 GrSurfaceProxy* proxy,
Michael Ludwig170de012019-11-15 21:55:18 +0000183 const GrSamplerState& sampler) {
184 GrTexture* tex = proxy->peekTexture();
Brian Salomonf29caf12019-11-15 12:12:28 -0500185 SkASSERT(fHasMode && textureDomain.modeX() == fModeX && textureDomain.modeY() == fModeY);
Michael Ludwig170de012019-11-15 21:55:18 +0000186 if (kIgnore_Mode != textureDomain.modeX() || kIgnore_Mode != textureDomain.modeY()) {
187 bool sendDecalData = textureDomain.modeX() == kDecal_Mode ||
188 textureDomain.modeY() == kDecal_Mode;
189
190 // If the texture is using nearest filtering, then the decal filter weight should step from
191 // 0 (texture) to 1 (transparent) one half pixel away from the domain. When doing any other
192 // form of filtering, the weight should be 1.0 so that it smoothly interpolates between the
193 // texture and transparent.
194 SkScalar decalFilterWeight = sampler.filter() == GrSamplerState::Filter::kNearest ?
195 SK_ScalarHalf : 1.0f;
Brian Salomon246bc3d2018-12-06 15:33:02 -0500196 SkScalar wInv, hInv, h;
Michael Ludwig8fa469d2019-11-25 16:08:44 -0500197 if (proxy->backendFormat().textureType() == GrTextureType::kRectangle) {
Brian Salomon246bc3d2018-12-06 15:33:02 -0500198 wInv = hInv = 1.f;
199 h = tex->height();
Michael Ludwig170de012019-11-15 21:55:18 +0000200
201 // Don't do any scaling by texture size for decal filter rate, it's already in pixels
202 if (sendDecalData) {
203 pdman.set3f(fDecalUni, 1.f, 1.f, decalFilterWeight);
204 }
Brian Salomon246bc3d2018-12-06 15:33:02 -0500205 } else {
206 wInv = SK_Scalar1 / tex->width();
207 hInv = SK_Scalar1 / tex->height();
208 h = 1.f;
Michael Ludwigbe315a22018-12-17 09:50:51 -0500209
Michael Ludwig170de012019-11-15 21:55:18 +0000210 if (sendDecalData) {
211 pdman.set3f(fDecalUni, tex->width(), tex->height(), decalFilterWeight);
212 }
Brian Salomon246bc3d2018-12-06 15:33:02 -0500213 }
Robert Phillipse98234f2017-01-09 14:23:59 -0500214
Michael Ludwig170de012019-11-15 21:55:18 +0000215 float values[kPrevDomainCount] = {
216 SkScalarToFloat(textureDomain.domain().fLeft * wInv),
217 SkScalarToFloat(textureDomain.domain().fTop * hInv),
218 SkScalarToFloat(textureDomain.domain().fRight * wInv),
219 SkScalarToFloat(textureDomain.domain().fBottom * hInv)
220 };
Robert Phillipse98234f2017-01-09 14:23:59 -0500221
Michael Ludwig8fa469d2019-11-25 16:08:44 -0500222 if (proxy->backendFormat().textureType() == GrTextureType::kRectangle) {
Michael Ludwig170de012019-11-15 21:55:18 +0000223 SkASSERT(values[0] >= 0.0f && values[0] <= proxy->width());
224 SkASSERT(values[1] >= 0.0f && values[1] <= proxy->height());
225 SkASSERT(values[2] >= 0.0f && values[2] <= proxy->width());
226 SkASSERT(values[3] >= 0.0f && values[3] <= proxy->height());
Brian Salomon246bc3d2018-12-06 15:33:02 -0500227 } else {
Michael Ludwig170de012019-11-15 21:55:18 +0000228 SkASSERT(values[0] >= 0.0f && values[0] <= 1.0f);
229 SkASSERT(values[1] >= 0.0f && values[1] <= 1.0f);
230 SkASSERT(values[2] >= 0.0f && values[2] <= 1.0f);
231 SkASSERT(values[3] >= 0.0f && values[3] <= 1.0f);
Brian Salomon246bc3d2018-12-06 15:33:02 -0500232 }
Robert Phillipse98234f2017-01-09 14:23:59 -0500233
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000234 // vertical flip if necessary
Robert Phillipsc686ce32017-07-21 14:12:29 -0400235 if (kBottomLeft_GrSurfaceOrigin == proxy->origin()) {
Michael Ludwig170de012019-11-15 21:55:18 +0000236 values[1] = h - values[1];
237 values[3] = h - values[3];
Brian Salomon246bc3d2018-12-06 15:33:02 -0500238
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000239 // The top and bottom were just flipped, so correct the ordering
240 // of elements so that values = (l, t, r, b).
Ben Wagnerf08d1d02018-06-18 15:11:00 -0400241 using std::swap;
Michael Ludwig170de012019-11-15 21:55:18 +0000242 swap(values[1], values[3]);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000243 }
Michael Ludwig170de012019-11-15 21:55:18 +0000244 if (0 != memcmp(values, fPrevDomain, kPrevDomainCount * sizeof(float))) {
245 pdman.set4fv(fDomainUni, 1, values);
246 memcpy(fPrevDomain, values, kPrevDomainCount * sizeof(float));
247 }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000248 }
249}
250
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000251///////////////////////////////////////////////////////////////////////////////
Brian Salomon587e08f2017-01-27 10:59:27 -0500252
Michael Ludwig170de012019-11-15 21:55:18 +0000253std::unique_ptr<GrFragmentProcessor> GrTextureDomainEffect::Make(
Michael Ludwig8fa469d2019-11-25 16:08:44 -0500254 sk_sp<GrSurfaceProxy> proxy,
Brian Salomonfc118442019-11-22 19:09:27 -0500255 SkAlphaType srcAlphaType,
Michael Ludwig170de012019-11-15 21:55:18 +0000256 const SkMatrix& matrix,
257 const SkRect& domain,
258 GrTextureDomain::Mode mode,
259 GrSamplerState::Filter filterMode) {
Brian Salomonfc118442019-11-22 19:09:27 -0500260 return Make(std::move(proxy), srcAlphaType, matrix, domain, mode, mode,
Michael Ludwig170de012019-11-15 21:55:18 +0000261 GrSamplerState(GrSamplerState::WrapMode::kClamp, filterMode));
Michael Ludwigbe315a22018-12-17 09:50:51 -0500262}
263
Michael Ludwig8fa469d2019-11-25 16:08:44 -0500264std::unique_ptr<GrFragmentProcessor> GrTextureDomainEffect::Make(sk_sp<GrSurfaceProxy> proxy,
Brian Salomonfc118442019-11-22 19:09:27 -0500265 SkAlphaType srcAlphaType,
266 const SkMatrix& matrix,
267 const SkRect& domain,
268 GrTextureDomain::Mode modeX,
269 GrTextureDomain::Mode modeY,
270 const GrSamplerState& sampler) {
Michael Ludwigbe315a22018-12-17 09:50:51 -0500271 // If both domain modes happen to be ignore, it would be faster to just drop the domain logic
Michael Ludwig170de012019-11-15 21:55:18 +0000272 // entirely Technically, we could also use the simple texture effect if the domain modes agree
273 // with the sampler modes and the proxy is the same size as the domain. It's a lot easier for
274 // calling code to detect these cases and handle it themselves.
275 return std::unique_ptr<GrFragmentProcessor>(new GrTextureDomainEffect(
Brian Salomonfc118442019-11-22 19:09:27 -0500276 std::move(proxy), srcAlphaType, matrix, domain, modeX, modeY, sampler));
Robert Phillips40fd7c92017-01-30 08:06:27 -0500277}
278
Michael Ludwig8fa469d2019-11-25 16:08:44 -0500279GrTextureDomainEffect::GrTextureDomainEffect(sk_sp<GrSurfaceProxy> proxy,
Brian Salomonfc118442019-11-22 19:09:27 -0500280 SkAlphaType srcAlphaType,
Michael Ludwig170de012019-11-15 21:55:18 +0000281 const SkMatrix& matrix,
282 const SkRect& domain,
283 GrTextureDomain::Mode modeX,
284 GrTextureDomain::Mode modeY,
285 const GrSamplerState& sampler)
286 : INHERITED(kGrTextureDomainEffect_ClassID,
Brian Salomonfc118442019-11-22 19:09:27 -0500287 ModulateForSamplerOptFlags(
288 srcAlphaType, GrTextureDomain::IsDecalSampled(sampler, modeX, modeY)))
Michael Ludwig170de012019-11-15 21:55:18 +0000289 , fCoordTransform(matrix, proxy.get())
290 , fTextureDomain(proxy.get(), domain, modeX, modeY)
291 , fTextureSampler(std::move(proxy), sampler) {
292 SkASSERT((modeX != GrTextureDomain::kRepeat_Mode && modeY != GrTextureDomain::kRepeat_Mode) ||
293 sampler.filter() == GrSamplerState::Filter::kNearest);
Brian Salomon6cd51b52017-07-26 19:07:15 -0400294 this->addCoordTransform(&fCoordTransform);
Michael Ludwig170de012019-11-15 21:55:18 +0000295 this->setTextureSamplerCnt(1);
Robert Phillips40fd7c92017-01-30 08:06:27 -0500296}
297
Michael Ludwig170de012019-11-15 21:55:18 +0000298GrTextureDomainEffect::GrTextureDomainEffect(const GrTextureDomainEffect& that)
299 : INHERITED(kGrTextureDomainEffect_ClassID, that.optimizationFlags())
Brian Salomon3f6f9652017-07-28 07:34:05 -0400300 , fCoordTransform(that.fCoordTransform)
Michael Ludwig170de012019-11-15 21:55:18 +0000301 , fTextureDomain(that.fTextureDomain)
302 , fTextureSampler(that.fTextureSampler) {
Brian Salomon3f6f9652017-07-28 07:34:05 -0400303 this->addCoordTransform(&fCoordTransform);
Michael Ludwig170de012019-11-15 21:55:18 +0000304 this->setTextureSamplerCnt(1);
Brian Salomon3f6f9652017-07-28 07:34:05 -0400305}
306
Michael Ludwig170de012019-11-15 21:55:18 +0000307void GrTextureDomainEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
308 GrProcessorKeyBuilder* b) const {
309 b->add32(GrTextureDomain::GLDomain::DomainKey(fTextureDomain));
joshualitteb2a6762014-12-04 11:35:33 -0800310}
311
Michael Ludwig170de012019-11-15 21:55:18 +0000312GrGLSLFragmentProcessor* GrTextureDomainEffect::onCreateGLSLInstance() const {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400313 class GLSLProcessor : public GrGLSLFragmentProcessor {
314 public:
315 void emitCode(EmitArgs& args) override {
Michael Ludwig170de012019-11-15 21:55:18 +0000316 const GrTextureDomainEffect& tde = args.fFp.cast<GrTextureDomainEffect>();
317 const GrTextureDomain& domain = tde.fTextureDomain;
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400318
Michael Ludwig170de012019-11-15 21:55:18 +0000319 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400320 SkString coords2D =
Michael Ludwig170de012019-11-15 21:55:18 +0000321 fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
Brian Osmanc4689632016-12-19 17:04:59 -0500322
Michael Ludwig170de012019-11-15 21:55:18 +0000323 fGLDomain.sampleTexture(fragBuilder,
324 args.fUniformHandler,
325 args.fShaderCaps,
326 domain,
327 args.fOutputColor,
328 coords2D,
329 args.fTexSamplers[0],
330 args.fInputColor);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400331 }
332
333 protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400334 void onSetData(const GrGLSLProgramDataManager& pdman,
335 const GrFragmentProcessor& fp) override {
Michael Ludwig170de012019-11-15 21:55:18 +0000336 const GrTextureDomainEffect& tde = fp.cast<GrTextureDomainEffect>();
337 const GrTextureDomain& domain = tde.fTextureDomain;
Michael Ludwig8fa469d2019-11-25 16:08:44 -0500338 GrSurfaceProxy* proxy = tde.textureSampler(0).proxy();
Michael Ludwig170de012019-11-15 21:55:18 +0000339
340 fGLDomain.setData(pdman, domain, proxy, tde.textureSampler(0).samplerState());
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400341 }
342
343 private:
344 GrTextureDomain::GLDomain fGLDomain;
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400345 };
346
347 return new GLSLProcessor;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000348}
349
Michael Ludwig170de012019-11-15 21:55:18 +0000350bool GrTextureDomainEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
351 const GrTextureDomainEffect& s = sBase.cast<GrTextureDomainEffect>();
352 return this->fTextureDomain == s.fTextureDomain;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000353}
354
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000355///////////////////////////////////////////////////////////////////////////////
356
Michael Ludwig170de012019-11-15 21:55:18 +0000357GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrTextureDomainEffect);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000358
Hal Canary6f6961e2017-01-31 13:50:44 -0500359#if GR_TEST_UTILS
Michael Ludwig170de012019-11-15 21:55:18 +0000360std::unique_ptr<GrFragmentProcessor> GrTextureDomainEffect::TestCreate(GrProcessorTestData* d) {
361 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
362 : GrProcessorUnitTest::kAlphaTextureIdx;
363 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000364 SkRect domain;
Michael Ludwig170de012019-11-15 21:55:18 +0000365 domain.fLeft = d->fRandom->nextRangeScalar(0, proxy->width());
366 domain.fRight = d->fRandom->nextRangeScalar(domain.fLeft, proxy->width());
367 domain.fTop = d->fRandom->nextRangeScalar(0, proxy->height());
368 domain.fBottom = d->fRandom->nextRangeScalar(domain.fTop, proxy->height());
369 GrTextureDomain::Mode modeX =
370 (GrTextureDomain::Mode) d->fRandom->nextULessThan(GrTextureDomain::kModeCount);
371 GrTextureDomain::Mode modeY =
372 (GrTextureDomain::Mode) d->fRandom->nextULessThan(GrTextureDomain::kModeCount);
joshualitt0067ff52015-07-08 14:26:19 -0700373 const SkMatrix& matrix = GrTest::TestMatrix(d->fRandom);
Michael Ludwig170de012019-11-15 21:55:18 +0000374 bool bilerp = modeX != GrTextureDomain::kRepeat_Mode && modeY != GrTextureDomain::kRepeat_Mode ?
375 d->fRandom->nextBool() : false;
Brian Salomonfc118442019-11-22 19:09:27 -0500376 auto alphaType = static_cast<SkAlphaType>(
377 d->fRandom->nextRangeU(kUnknown_SkAlphaType + 1, kLastEnum_SkAlphaType));
378 return GrTextureDomainEffect::Make(std::move(proxy),
379 alphaType,
380 matrix,
381 domain,
382 modeX,
383 modeY,
384 GrSamplerState(GrSamplerState::WrapMode::kClamp,
385 bilerp ? GrSamplerState::Filter::kBilerp
386 : GrSamplerState::Filter::kNearest));
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400387}
Hal Canary6f6961e2017-01-31 13:50:44 -0500388#endif
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400389
390///////////////////////////////////////////////////////////////////////////////
Brian Salomonaff329b2017-08-11 09:40:37 -0400391std::unique_ptr<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::Make(
Michael Ludwig8fa469d2019-11-25 16:08:44 -0500392 sk_sp<GrSurfaceProxy> proxy, const SkIRect& subset, const SkIPoint& deviceSpaceOffset) {
Brian Salomonaff329b2017-08-11 09:40:37 -0400393 return std::unique_ptr<GrFragmentProcessor>(new GrDeviceSpaceTextureDecalFragmentProcessor(
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400394 std::move(proxy), subset, deviceSpaceOffset));
Robert Phillips40fd7c92017-01-30 08:06:27 -0500395}
396
397GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
Michael Ludwig8fa469d2019-11-25 16:08:44 -0500398 sk_sp<GrSurfaceProxy> proxy, const SkIRect& subset, const SkIPoint& deviceSpaceOffset)
Ethan Nicholasabff9562017-10-09 10:54:08 -0400399 : INHERITED(kGrDeviceSpaceTextureDecalFragmentProcessor_ClassID,
400 kCompatibleWithCoverageAsAlpha_OptimizationFlag)
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400401 , fTextureSampler(proxy, GrSamplerState::ClampNearest())
Michael Ludwigbe315a22018-12-17 09:50:51 -0500402 , fTextureDomain(proxy.get(),
403 GrTextureDomain::MakeTexelDomain(subset, GrTextureDomain::kDecal_Mode),
404 GrTextureDomain::kDecal_Mode, GrTextureDomain::kDecal_Mode) {
Brian Salomonf7dcd762018-07-30 14:48:15 -0400405 this->setTextureSamplerCnt(1);
Robert Phillips40fd7c92017-01-30 08:06:27 -0500406 fDeviceSpaceOffset.fX = deviceSpaceOffset.fX - subset.fLeft;
407 fDeviceSpaceOffset.fY = deviceSpaceOffset.fY - subset.fTop;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500408}
409
Brian Salomon1a2a7ab2017-07-26 13:11:51 -0400410GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
411 const GrDeviceSpaceTextureDecalFragmentProcessor& that)
Ethan Nicholasabff9562017-10-09 10:54:08 -0400412 : INHERITED(kGrDeviceSpaceTextureDecalFragmentProcessor_ClassID,
413 kCompatibleWithCoverageAsAlpha_OptimizationFlag)
Brian Salomon1a2a7ab2017-07-26 13:11:51 -0400414 , fTextureSampler(that.fTextureSampler)
415 , fTextureDomain(that.fTextureDomain)
416 , fDeviceSpaceOffset(that.fDeviceSpaceOffset) {
Brian Salomonf7dcd762018-07-30 14:48:15 -0400417 this->setTextureSamplerCnt(1);
Brian Salomon1a2a7ab2017-07-26 13:11:51 -0400418}
419
Brian Salomonaff329b2017-08-11 09:40:37 -0400420std::unique_ptr<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::clone() const {
421 return std::unique_ptr<GrFragmentProcessor>(
422 new GrDeviceSpaceTextureDecalFragmentProcessor(*this));
Brian Salomon1a2a7ab2017-07-26 13:11:51 -0400423}
424
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400425GrGLSLFragmentProcessor* GrDeviceSpaceTextureDecalFragmentProcessor::onCreateGLSLInstance() const {
426 class GLSLProcessor : public GrGLSLFragmentProcessor {
427 public:
428 void emitCode(EmitArgs& args) override {
429 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
430 args.fFp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
431 const char* scaleAndTranslateName;
432 fScaleAndTranslateUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400433 kHalf4_GrSLType,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400434 "scaleAndTranslate",
435 &scaleAndTranslateName);
Ethan Nicholase1f55022019-02-05 17:17:40 -0500436 args.fFragBuilder->codeAppendf("half2 coords = half2(sk_FragCoord.xy * %s.xy + %s.zw);",
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400437 scaleAndTranslateName, scaleAndTranslateName);
438 fGLDomain.sampleTexture(args.fFragBuilder,
439 args.fUniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500440 args.fShaderCaps,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400441 dstdfp.fTextureDomain,
442 args.fOutputColor,
443 SkString("coords"),
444 args.fTexSamplers[0],
445 args.fInputColor);
446 }
447
448 protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400449 void onSetData(const GrGLSLProgramDataManager& pdman,
450 const GrFragmentProcessor& fp) override {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400451 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
452 fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
Michael Ludwig8fa469d2019-11-25 16:08:44 -0500453 GrSurfaceProxy* proxy = dstdfp.textureSampler(0).proxy();
454 SkISize textureDims = proxy->backingStoreDimensions();
Robert Phillips9bee2e52017-05-29 12:37:20 -0400455
Michael Ludwigbe315a22018-12-17 09:50:51 -0500456 fGLDomain.setData(pdman, dstdfp.fTextureDomain, proxy,
457 dstdfp.textureSampler(0).samplerState());
Michael Ludwig8fa469d2019-11-25 16:08:44 -0500458 float iw = 1.f / textureDims.width();
459 float ih = 1.f / textureDims.height();
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400460 float scaleAndTransData[4] = {
461 iw, ih,
462 -dstdfp.fDeviceSpaceOffset.fX * iw, -dstdfp.fDeviceSpaceOffset.fY * ih
463 };
Robert Phillipsc686ce32017-07-21 14:12:29 -0400464 if (proxy->origin() == kBottomLeft_GrSurfaceOrigin) {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400465 scaleAndTransData[1] = -scaleAndTransData[1];
466 scaleAndTransData[3] = 1 - scaleAndTransData[3];
467 }
468 pdman.set4fv(fScaleAndTranslateUni, 1, scaleAndTransData);
469 }
470
471 private:
472 GrTextureDomain::GLDomain fGLDomain;
473 UniformHandle fScaleAndTranslateUni;
474 };
475
476 return new GLSLProcessor;
477}
478
479bool GrDeviceSpaceTextureDecalFragmentProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
480 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
481 fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
Brian Salomon1a2a7ab2017-07-26 13:11:51 -0400482 return dstdfp.fTextureSampler.proxy()->underlyingUniqueID() ==
483 fTextureSampler.proxy()->underlyingUniqueID() &&
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400484 dstdfp.fDeviceSpaceOffset == fDeviceSpaceOffset &&
485 dstdfp.fTextureDomain == fTextureDomain;
486}
487
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400488///////////////////////////////////////////////////////////////////////////////
489
490GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDeviceSpaceTextureDecalFragmentProcessor);
491
Hal Canary6f6961e2017-01-31 13:50:44 -0500492#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -0400493std::unique_ptr<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::TestCreate(
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400494 GrProcessorTestData* d) {
495 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
496 : GrProcessorUnitTest::kAlphaTextureIdx;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500497 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400498 SkIRect subset;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500499 subset.fLeft = d->fRandom->nextULessThan(proxy->width() - 1);
500 subset.fRight = d->fRandom->nextRangeU(subset.fLeft, proxy->width());
501 subset.fTop = d->fRandom->nextULessThan(proxy->height() - 1);
502 subset.fBottom = d->fRandom->nextRangeU(subset.fTop, proxy->height());
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400503 SkIPoint pt;
504 pt.fX = d->fRandom->nextULessThan(2048);
505 pt.fY = d->fRandom->nextULessThan(2048);
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400506 return GrDeviceSpaceTextureDecalFragmentProcessor::Make(std::move(proxy), subset, pt);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000507}
Hal Canary6f6961e2017-01-31 13:50:44 -0500508#endif