blob: 7a43328bc1743fd82b0e8c9cea88b3bb3fbb9ebf [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#include "GrTextureDomain.h"
Robert Phillips40fd7c92017-01-30 08:06:27 -05009
10#include "GrContext.h"
Brian Salomon94efbf52016-11-29 13:43:05 -050011#include "GrShaderCaps.h"
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000012#include "GrSimpleTextureEffect.h"
Robert Phillips40fd7c92017-01-30 08:06:27 -050013#include "GrSurfaceProxyPriv.h"
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000014#include "SkFloatingPoint.h"
Brian Osmanc4689632016-12-19 17:04:59 -050015#include "glsl/GrGLSLColorSpaceXformHelper.h"
egdaniel64c47282015-11-13 06:54:19 -080016#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel7ea439b2015-12-03 09:20:44 -080017#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniel018fb622015-10-28 07:26:40 -070018#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080019#include "glsl/GrGLSLShaderBuilder.h"
egdaniel7ea439b2015-12-03 09:20:44 -080020#include "glsl/GrGLSLUniformHandler.h"
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000021
Robert Phillips40fd7c92017-01-30 08:06:27 -050022static bool can_ignore_rect(GrSurfaceProxy* proxy, const SkRect& domain) {
23 if (proxy->priv().isExact()) {
24 const SkIRect kFullRect = SkIRect::MakeWH(proxy->width(), proxy->height());
25
26 return domain.contains(kFullRect);
27 }
28
29 return false;
30}
31
Robert Phillipse98234f2017-01-09 14:23:59 -050032static bool can_ignore_rect(GrTexture* tex, const SkRect& domain) {
33 // This logic is relying on the instantiated size of 'tex'. In the deferred world it
34 // will have to change so this logic only fires for kExact texture proxies. This shouldn't
35 // change the actual behavior of Ganesh since shaders shouldn't be accessing pixels outside
36 // of the content rectangle.
37 const SkIRect kFullRect = SkIRect::MakeWH(tex->width(), tex->height());
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000038
Robert Phillipse98234f2017-01-09 14:23:59 -050039 return domain.contains(kFullRect);
40}
41
42GrTextureDomain::GrTextureDomain(GrTexture* tex, const SkRect& domain, Mode mode, int index)
Robert Phillips40fd7c92017-01-30 08:06:27 -050043 : fMode(mode)
44 , fIndex(index) {
Robert Phillipse98234f2017-01-09 14:23:59 -050045
46 if (kIgnore_Mode == fMode) {
47 return;
48 }
49
50 if (kClamp_Mode == mode && can_ignore_rect(tex, domain)) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000051 fMode = kIgnore_Mode;
Robert Phillipse98234f2017-01-09 14:23:59 -050052 return;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000053 }
54
Robert Phillipse98234f2017-01-09 14:23:59 -050055 const SkRect kFullRect = SkRect::MakeIWH(tex->width(), tex->height());
56
57 // We don't currently handle domains that are empty or don't intersect the texture.
58 // It is OK if the domain rect is a line or point, but it should not be inverted. We do not
59 // handle rects that do not intersect the [0..1]x[0..1] rect.
60 SkASSERT(domain.fLeft <= domain.fRight);
61 SkASSERT(domain.fTop <= domain.fBottom);
62 fDomain.fLeft = SkScalarPin(domain.fLeft, 0.0f, kFullRect.fRight);
63 fDomain.fRight = SkScalarPin(domain.fRight, fDomain.fLeft, kFullRect.fRight);
64 fDomain.fTop = SkScalarPin(domain.fTop, 0.0f, kFullRect.fBottom);
65 fDomain.fBottom = SkScalarPin(domain.fBottom, fDomain.fTop, kFullRect.fBottom);
66 SkASSERT(fDomain.fLeft <= fDomain.fRight);
67 SkASSERT(fDomain.fTop <= fDomain.fBottom);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000068}
69
Robert Phillips40fd7c92017-01-30 08:06:27 -050070GrTextureDomain::GrTextureDomain(GrTextureProxy* proxy, const SkRect& domain, Mode mode, int index)
71 : fMode(mode)
72 , fIndex(index) {
73
74 if (kIgnore_Mode == fMode) {
75 return;
76 }
77
78 if (kClamp_Mode == mode && can_ignore_rect(proxy, domain)) {
79 fMode = kIgnore_Mode;
80 return;
81 }
82
83 const SkRect kFullRect = SkRect::MakeIWH(proxy->width(), proxy->height());
84
85 // We don't currently handle domains that are empty or don't intersect the texture.
86 // It is OK if the domain rect is a line or point, but it should not be inverted. We do not
87 // handle rects that do not intersect the [0..1]x[0..1] rect.
88 SkASSERT(domain.fLeft <= domain.fRight);
89 SkASSERT(domain.fTop <= domain.fBottom);
90 fDomain.fLeft = SkScalarPin(domain.fLeft, 0.0f, kFullRect.fRight);
91 fDomain.fRight = SkScalarPin(domain.fRight, fDomain.fLeft, kFullRect.fRight);
92 fDomain.fTop = SkScalarPin(domain.fTop, 0.0f, kFullRect.fBottom);
93 fDomain.fBottom = SkScalarPin(domain.fBottom, fDomain.fTop, kFullRect.fBottom);
94 SkASSERT(fDomain.fLeft <= fDomain.fRight);
95 SkASSERT(fDomain.fTop <= fDomain.fBottom);
96}
97
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000098//////////////////////////////////////////////////////////////////////////////
99
egdaniel2d721d32015-11-11 13:06:05 -0800100void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
egdaniel7ea439b2015-12-03 09:20:44 -0800101 GrGLSLUniformHandler* uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500102 const GrShaderCaps* shaderCaps,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000103 const GrTextureDomain& textureDomain,
104 const char* outColor,
105 const SkString& inCoords,
egdaniel09aa1fc2016-04-20 07:09:46 -0700106 GrGLSLFragmentProcessor::SamplerHandle sampler,
Brian Osmanc4689632016-12-19 17:04:59 -0500107 const char* inModulateColor,
108 GrGLSLColorSpaceXformHelper* colorXformHelper) {
reed@google.comd7b1af62013-12-09 20:31:50 +0000109 SkASSERT((Mode)-1 == fMode || textureDomain.mode() == fMode);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000110 SkDEBUGCODE(fMode = textureDomain.mode();)
111
joshualitt5ae5fc52014-07-29 12:59:27 -0700112 if (textureDomain.mode() != kIgnore_Mode && !fDomainUni.isValid()) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000113 const char* name;
114 SkString uniName("TexDom");
115 if (textureDomain.fIndex >= 0) {
116 uniName.appendS32(textureDomain.fIndex);
117 }
cdalton5e58cee2016-02-11 12:49:47 -0800118 fDomainUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800119 kVec4f_GrSLType, kDefault_GrSLPrecision,
120 uniName.c_str(), &name);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000121 fDomainName = name;
122 }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000123
joshualitt5ae5fc52014-07-29 12:59:27 -0700124 switch (textureDomain.mode()) {
125 case kIgnore_Mode: {
jvanverth3fc65602015-07-22 08:41:51 -0700126 builder->codeAppendf("%s = ", outColor);
Brian Osmanc4689632016-12-19 17:04:59 -0500127 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
128 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700129 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700130 break;
131 }
132 case kClamp_Mode: {
133 SkString clampedCoords;
jvanverth3fc65602015-07-22 08:41:51 -0700134 clampedCoords.appendf("clamp(%s, %s.xy, %s.zw)",
joshualitt5ae5fc52014-07-29 12:59:27 -0700135 inCoords.c_str(), fDomainName.c_str(), fDomainName.c_str());
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000136
jvanverth3fc65602015-07-22 08:41:51 -0700137 builder->codeAppendf("%s = ", outColor);
Brian Osmanc4689632016-12-19 17:04:59 -0500138 builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
139 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700140 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700141 break;
142 }
143 case kDecal_Mode: {
144 // Add a block since we're going to declare variables.
egdaniel2d721d32015-11-11 13:06:05 -0800145 GrGLSLShaderBuilder::ShaderBlock block(builder);
joshualitt5ae5fc52014-07-29 12:59:27 -0700146
147 const char* domain = fDomainName.c_str();
Brian Salomon1edc5b92016-11-29 13:43:46 -0500148 if (!shaderCaps->canUseAnyFunctionInShader()) {
joshualitt5ae5fc52014-07-29 12:59:27 -0700149 // On the NexusS and GalaxyNexus, the other path (with the 'any'
150 // call) causes the compilation error "Calls to any function that
151 // may require a gradient calculation inside a conditional block
152 // may return undefined results". This appears to be an issue with
153 // the 'any' call since even the simple "result=black; if (any())
154 // result=white;" code fails to compile.
jvanverth3fc65602015-07-22 08:41:51 -0700155 builder->codeAppend("vec4 outside = vec4(0.0, 0.0, 0.0, 0.0);");
156 builder->codeAppend("vec4 inside = ");
Brian Osmanc4689632016-12-19 17:04:59 -0500157 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
158 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700159 builder->codeAppend(";");
halcanary9d524f22016-03-29 09:03:52 -0700160
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500161 builder->codeAppendf("highp float x = (%s).x;", inCoords.c_str());
162 builder->codeAppendf("highp float y = (%s).y;", inCoords.c_str());
joshualitt5ae5fc52014-07-29 12:59:27 -0700163
jvanverth3fc65602015-07-22 08:41:51 -0700164 builder->codeAppendf("x = abs(2.0*(x - %s.x)/(%s.z - %s.x) - 1.0);",
165 domain, domain, domain);
166 builder->codeAppendf("y = abs(2.0*(y - %s.y)/(%s.w - %s.y) - 1.0);",
167 domain, domain, domain);
168 builder->codeAppend("float blend = step(1.0, max(x, y));");
169 builder->codeAppendf("%s = mix(inside, outside, blend);", outColor);
joshualitt5ae5fc52014-07-29 12:59:27 -0700170 } else {
jvanverth3fc65602015-07-22 08:41:51 -0700171 builder->codeAppend("bvec4 outside;\n");
172 builder->codeAppendf("outside.xy = lessThan(%s, %s.xy);", inCoords.c_str(),
joshualitt5ae5fc52014-07-29 12:59:27 -0700173 domain);
jvanverth3fc65602015-07-22 08:41:51 -0700174 builder->codeAppendf("outside.zw = greaterThan(%s, %s.zw);", inCoords.c_str(),
joshualitt5ae5fc52014-07-29 12:59:27 -0700175 domain);
jvanverth3fc65602015-07-22 08:41:51 -0700176 builder->codeAppendf("%s = any(outside) ? vec4(0.0, 0.0, 0.0, 0.0) : ",
joshualitt5ae5fc52014-07-29 12:59:27 -0700177 outColor);
Brian Osmanc4689632016-12-19 17:04:59 -0500178 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
179 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700180 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700181 }
182 break;
183 }
184 case kRepeat_Mode: {
185 SkString clampedCoords;
jvanverth3fc65602015-07-22 08:41:51 -0700186 clampedCoords.printf("mod(%s - %s.xy, %s.zw - %s.xy) + %s.xy",
joshualitt5ae5fc52014-07-29 12:59:27 -0700187 inCoords.c_str(), fDomainName.c_str(), fDomainName.c_str(),
188 fDomainName.c_str(), fDomainName.c_str());
189
jvanverth3fc65602015-07-22 08:41:51 -0700190 builder->codeAppendf("%s = ", outColor);
Brian Osmanc4689632016-12-19 17:04:59 -0500191 builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
192 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700193 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700194 break;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000195 }
196 }
197}
198
egdaniel018fb622015-10-28 07:26:40 -0700199void GrTextureDomain::GLDomain::setData(const GrGLSLProgramDataManager& pdman,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000200 const GrTextureDomain& textureDomain,
Robert Phillipse98234f2017-01-09 14:23:59 -0500201 GrTexture* tex) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000202 SkASSERT(textureDomain.mode() == fMode);
203 if (kIgnore_Mode != textureDomain.mode()) {
Robert Phillipse98234f2017-01-09 14:23:59 -0500204 SkScalar wInv = SK_Scalar1 / tex->width();
205 SkScalar hInv = SK_Scalar1 / tex->height();
206
egdaniel018fb622015-10-28 07:26:40 -0700207 float values[kPrevDomainCount] = {
Robert Phillipse98234f2017-01-09 14:23:59 -0500208 SkScalarToFloat(textureDomain.domain().fLeft * wInv),
209 SkScalarToFloat(textureDomain.domain().fTop * hInv),
210 SkScalarToFloat(textureDomain.domain().fRight * wInv),
211 SkScalarToFloat(textureDomain.domain().fBottom * hInv)
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000212 };
Robert Phillipse98234f2017-01-09 14:23:59 -0500213
214 SkASSERT(values[0] >= 0.0f && values[0] <= 1.0f);
215 SkASSERT(values[1] >= 0.0f && values[1] <= 1.0f);
216 SkASSERT(values[2] >= 0.0f && values[2] <= 1.0f);
217 SkASSERT(values[3] >= 0.0f && values[3] <= 1.0f);
218
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000219 // vertical flip if necessary
Robert Phillipse98234f2017-01-09 14:23:59 -0500220 if (kBottomLeft_GrSurfaceOrigin == tex->origin()) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000221 values[1] = 1.0f - values[1];
222 values[3] = 1.0f - values[3];
223 // The top and bottom were just flipped, so correct the ordering
224 // of elements so that values = (l, t, r, b).
225 SkTSwap(values[1], values[3]);
226 }
egdaniel018fb622015-10-28 07:26:40 -0700227 if (0 != memcmp(values, fPrevDomain, kPrevDomainCount * sizeof(float))) {
kkinnunen7510b222014-07-30 00:04:16 -0700228 pdman.set4fv(fDomainUni, 1, values);
egdaniel018fb622015-10-28 07:26:40 -0700229 memcpy(fPrevDomain, values, kPrevDomainCount * sizeof(float));
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000230 }
231 }
232}
233
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000234///////////////////////////////////////////////////////////////////////////////
bungeman06ca8ec2016-06-09 08:01:03 -0700235sk_sp<GrFragmentProcessor> GrTextureDomainEffect::Make(GrTexture* texture,
brianosman54f30c12016-07-18 10:53:52 -0700236 sk_sp<GrColorSpaceXform> colorSpaceXform,
bungeman06ca8ec2016-06-09 08:01:03 -0700237 const SkMatrix& matrix,
238 const SkRect& domain,
239 GrTextureDomain::Mode mode,
Brian Salomon514baff2016-11-17 15:17:07 -0500240 GrSamplerParams::FilterMode filterMode) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000241 if (GrTextureDomain::kIgnore_Mode == mode ||
Robert Phillipse98234f2017-01-09 14:23:59 -0500242 (GrTextureDomain::kClamp_Mode == mode && can_ignore_rect(texture, domain))) {
brianosman54f30c12016-07-18 10:53:52 -0700243 return GrSimpleTextureEffect::Make(texture, std::move(colorSpaceXform), matrix, filterMode);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000244 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700245 return sk_sp<GrFragmentProcessor>(
brianosman54f30c12016-07-18 10:53:52 -0700246 new GrTextureDomainEffect(texture, std::move(colorSpaceXform), matrix, domain, mode,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400247 filterMode));
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000248 }
249}
250
Brian Salomon587e08f2017-01-27 10:59:27 -0500251inline GrFragmentProcessor::OptimizationFlags GrTextureDomainEffect::OptFlags(
Robert Phillips40fd7c92017-01-30 08:06:27 -0500252 GrPixelConfig config, GrTextureDomain::Mode mode) {
253 if (mode == GrTextureDomain::kDecal_Mode || !GrPixelConfigIsOpaque(config)) {
Brian Salomonf3b995b2017-02-15 10:22:23 -0500254 return GrFragmentProcessor::kCompatibleWithCoverageAsAlpha_OptimizationFlag;
Brian Salomon587e08f2017-01-27 10:59:27 -0500255 } else {
Brian Salomonf3b995b2017-02-15 10:22:23 -0500256 return GrFragmentProcessor::kCompatibleWithCoverageAsAlpha_OptimizationFlag |
Brian Salomon587e08f2017-01-27 10:59:27 -0500257 GrFragmentProcessor::kPreservesOpaqueInput_OptimizationFlag;
258 }
259}
260
bsalomon4a339522015-10-06 08:40:50 -0700261GrTextureDomainEffect::GrTextureDomainEffect(GrTexture* texture,
brianosman54f30c12016-07-18 10:53:52 -0700262 sk_sp<GrColorSpaceXform> colorSpaceXform,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000263 const SkMatrix& matrix,
264 const SkRect& domain,
265 GrTextureDomain::Mode mode,
Brian Salomon514baff2016-11-17 15:17:07 -0500266 GrSamplerParams::FilterMode filterMode)
Brian Salomon587e08f2017-01-27 10:59:27 -0500267 : GrSingleTextureEffect(texture, std::move(colorSpaceXform), matrix, filterMode,
Robert Phillips40fd7c92017-01-30 08:06:27 -0500268 OptFlags(texture->config(), mode))
Brian Salomon587e08f2017-01-27 10:59:27 -0500269 , fTextureDomain(texture, domain, mode) {
joshualitt5ae5fc52014-07-29 12:59:27 -0700270 SkASSERT(mode != GrTextureDomain::kRepeat_Mode ||
Brian Salomon514baff2016-11-17 15:17:07 -0500271 filterMode == GrSamplerParams::kNone_FilterMode);
joshualitteb2a6762014-12-04 11:35:33 -0800272 this->initClassID<GrTextureDomainEffect>();
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000273}
274
Robert Phillips40fd7c92017-01-30 08:06:27 -0500275sk_sp<GrFragmentProcessor> GrTextureDomainEffect::Make(GrContext* context,
276 sk_sp<GrTextureProxy> proxy,
277 sk_sp<GrColorSpaceXform> colorSpaceXform,
278 const SkMatrix& matrix,
279 const SkRect& domain,
280 GrTextureDomain::Mode mode,
281 GrSamplerParams::FilterMode filterMode) {
282 if (GrTextureDomain::kIgnore_Mode == mode ||
283 (GrTextureDomain::kClamp_Mode == mode && can_ignore_rect(proxy.get(), domain))) {
284 return GrSimpleTextureEffect::Make(context, std::move(proxy), std::move(colorSpaceXform),
285 matrix, filterMode);
286 } else {
287 return sk_sp<GrFragmentProcessor>(
288 new GrTextureDomainEffect(context, std::move(proxy), std::move(colorSpaceXform),
289 matrix, domain, mode, filterMode));
290 }
291}
292
293GrTextureDomainEffect::GrTextureDomainEffect(GrContext* context,
294 sk_sp<GrTextureProxy> proxy,
295 sk_sp<GrColorSpaceXform> colorSpaceXform,
296 const SkMatrix& matrix,
297 const SkRect& domain,
298 GrTextureDomain::Mode mode,
299 GrSamplerParams::FilterMode filterMode)
300 : GrSingleTextureEffect(context, OptFlags(proxy->config(), mode), proxy,
301 std::move(colorSpaceXform), matrix, filterMode)
302 , fTextureDomain(proxy.get(), domain, mode) {
303 SkASSERT(mode != GrTextureDomain::kRepeat_Mode ||
304 filterMode == GrSamplerParams::kNone_FilterMode);
305 this->initClassID<GrTextureDomainEffect>();
306}
307
Brian Salomon94efbf52016-11-29 13:43:05 -0500308void GrTextureDomainEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800309 GrProcessorKeyBuilder* b) const {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400310 b->add32(GrTextureDomain::GLDomain::DomainKey(fTextureDomain));
Brian Osman70826d72016-12-20 15:06:18 -0500311 b->add32(GrColorSpaceXform::XformKey(this->colorSpaceXform()));
joshualitteb2a6762014-12-04 11:35:33 -0800312}
313
egdaniel57d3b032015-11-13 11:57:27 -0800314GrGLSLFragmentProcessor* GrTextureDomainEffect::onCreateGLSLInstance() const {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400315 class GLSLProcessor : public GrGLSLFragmentProcessor {
316 public:
317 void emitCode(EmitArgs& args) override {
318 const GrTextureDomainEffect& tde = args.fFp.cast<GrTextureDomainEffect>();
319 const GrTextureDomain& domain = tde.fTextureDomain;
320
321 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
322 SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
Brian Osmanc4689632016-12-19 17:04:59 -0500323
Brian Osmanc624d9d2017-03-08 11:42:02 -0500324 fColorSpaceHelper.emitCode(args.fUniformHandler, tde.colorSpaceXform());
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400325 fGLDomain.sampleTexture(fragBuilder,
326 args.fUniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500327 args.fShaderCaps,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400328 domain,
329 args.fOutputColor,
330 coords2D,
331 args.fTexSamplers[0],
Brian Osmanc4689632016-12-19 17:04:59 -0500332 args.fInputColor,
Brian Osmanc624d9d2017-03-08 11:42:02 -0500333 &fColorSpaceHelper);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400334 }
335
336 protected:
337 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& fp) override {
338 const GrTextureDomainEffect& tde = fp.cast<GrTextureDomainEffect>();
339 const GrTextureDomain& domain = tde.fTextureDomain;
Robert Phillipse98234f2017-01-09 14:23:59 -0500340 fGLDomain.setData(pdman, domain, tde.textureSampler(0).texture());
Brian Osmanc4689632016-12-19 17:04:59 -0500341 if (SkToBool(tde.colorSpaceXform())) {
Brian Osmanc624d9d2017-03-08 11:42:02 -0500342 fColorSpaceHelper.setData(pdman, tde.colorSpaceXform());
Brian Osmanc4689632016-12-19 17:04:59 -0500343 }
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400344 }
345
346 private:
347 GrTextureDomain::GLDomain fGLDomain;
Brian Osmanc624d9d2017-03-08 11:42:02 -0500348 GrGLSLColorSpaceXformHelper fColorSpaceHelper;
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400349 };
350
351 return new GLSLProcessor;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000352}
353
bsalomon0e08fc12014-10-15 08:19:04 -0700354bool GrTextureDomainEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
joshualitt49586be2014-09-16 08:21:41 -0700355 const GrTextureDomainEffect& s = sBase.cast<GrTextureDomainEffect>();
Brian Salomona7c4c292016-11-17 12:47:06 -0500356 return this->fTextureDomain == s.fTextureDomain;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000357}
358
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000359///////////////////////////////////////////////////////////////////////////////
360
joshualittb0a8a372014-09-23 09:50:21 -0700361GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrTextureDomainEffect);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000362
Hal Canary6f6961e2017-01-31 13:50:44 -0500363#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700364sk_sp<GrFragmentProcessor> GrTextureDomainEffect::TestCreate(GrProcessorTestData* d) {
Robert Phillips40fd7c92017-01-30 08:06:27 -0500365 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
366 : GrProcessorUnitTest::kAlphaTextureIdx;
367 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000368 SkRect domain;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500369 domain.fLeft = d->fRandom->nextRangeScalar(0, proxy->width());
370 domain.fRight = d->fRandom->nextRangeScalar(domain.fLeft, proxy->width());
371 domain.fTop = d->fRandom->nextRangeScalar(0, proxy->height());
372 domain.fBottom = d->fRandom->nextRangeScalar(domain.fTop, proxy->height());
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000373 GrTextureDomain::Mode mode =
joshualitt0067ff52015-07-08 14:26:19 -0700374 (GrTextureDomain::Mode) d->fRandom->nextULessThan(GrTextureDomain::kModeCount);
375 const SkMatrix& matrix = GrTest::TestMatrix(d->fRandom);
376 bool bilerp = mode != GrTextureDomain::kRepeat_Mode ? d->fRandom->nextBool() : false;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500377 sk_sp<GrColorSpaceXform> colorSpaceXform = GrTest::TestColorXform(d->fRandom);
378 return GrTextureDomainEffect::Make(d->context(),
379 std::move(proxy),
380 std::move(colorSpaceXform),
381 matrix,
382 domain,
383 mode,
384 bilerp ? GrSamplerParams::kBilerp_FilterMode
385 : GrSamplerParams::kNone_FilterMode);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400386}
Hal Canary6f6961e2017-01-31 13:50:44 -0500387#endif
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400388
389///////////////////////////////////////////////////////////////////////////////
390
391sk_sp<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::Make(GrTexture* texture,
392 const SkIRect& subset, const SkIPoint& deviceSpaceOffset) {
393 return sk_sp<GrFragmentProcessor>(new GrDeviceSpaceTextureDecalFragmentProcessor(
394 texture, subset, deviceSpaceOffset));
395}
396
397GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
398 GrTexture* texture, const SkIRect& subset, const SkIPoint& deviceSpaceOffset)
Brian Salomonf3b995b2017-02-15 10:22:23 -0500399 : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
Brian Salomon587e08f2017-01-27 10:59:27 -0500400 , fTextureSampler(texture, GrSamplerParams::ClampNoFilter())
Robert Phillipse98234f2017-01-09 14:23:59 -0500401 , fTextureDomain(texture, GrTextureDomain::MakeTexelDomain(subset),
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400402 GrTextureDomain::kDecal_Mode) {
Brian Salomon0bbecb22016-11-17 11:38:22 -0500403 this->addTextureSampler(&fTextureSampler);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400404 fDeviceSpaceOffset.fX = deviceSpaceOffset.fX - subset.fLeft;
405 fDeviceSpaceOffset.fY = deviceSpaceOffset.fY - subset.fTop;
406 this->initClassID<GrDeviceSpaceTextureDecalFragmentProcessor>();
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400407}
408
Robert Phillips40fd7c92017-01-30 08:06:27 -0500409sk_sp<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::Make(
410 GrContext* context,
411 sk_sp<GrTextureProxy> proxy,
412 const SkIRect& subset,
413 const SkIPoint& deviceSpaceOffset) {
414 return sk_sp<GrFragmentProcessor>(new GrDeviceSpaceTextureDecalFragmentProcessor(
415 context, std::move(proxy), subset, deviceSpaceOffset));
416}
417
418GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
419 GrContext* context,
420 sk_sp<GrTextureProxy> proxy,
421 const SkIRect& subset,
422 const SkIPoint& deviceSpaceOffset)
Brian Salomonf3b995b2017-02-15 10:22:23 -0500423 : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
Brian Osman32342f02017-03-04 08:12:46 -0500424 , fTextureSampler(context->resourceProvider(), proxy, GrSamplerParams::ClampNoFilter())
Robert Phillips40fd7c92017-01-30 08:06:27 -0500425 , fTextureDomain(proxy.get(), GrTextureDomain::MakeTexelDomain(subset),
426 GrTextureDomain::kDecal_Mode) {
427 this->addTextureSampler(&fTextureSampler);
428 fDeviceSpaceOffset.fX = deviceSpaceOffset.fX - subset.fLeft;
429 fDeviceSpaceOffset.fY = deviceSpaceOffset.fY - subset.fTop;
430 this->initClassID<GrDeviceSpaceTextureDecalFragmentProcessor>();
431}
432
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400433GrGLSLFragmentProcessor* GrDeviceSpaceTextureDecalFragmentProcessor::onCreateGLSLInstance() const {
434 class GLSLProcessor : public GrGLSLFragmentProcessor {
435 public:
436 void emitCode(EmitArgs& args) override {
437 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
438 args.fFp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
439 const char* scaleAndTranslateName;
440 fScaleAndTranslateUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
441 kVec4f_GrSLType,
442 kDefault_GrSLPrecision,
443 "scaleAndTranslate",
444 &scaleAndTranslateName);
Ethan Nicholas38657112017-02-09 17:01:22 -0500445 args.fFragBuilder->codeAppendf("vec2 coords = sk_FragCoord.xy * %s.xy + %s.zw;",
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400446 scaleAndTranslateName, scaleAndTranslateName);
447 fGLDomain.sampleTexture(args.fFragBuilder,
448 args.fUniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500449 args.fShaderCaps,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400450 dstdfp.fTextureDomain,
451 args.fOutputColor,
452 SkString("coords"),
453 args.fTexSamplers[0],
454 args.fInputColor);
455 }
456
457 protected:
458 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& fp) override {
459 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
460 fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
Brian Salomondb4183d2016-11-17 12:48:40 -0500461 GrTexture* texture = dstdfp.textureSampler(0).texture();
Robert Phillipse98234f2017-01-09 14:23:59 -0500462 fGLDomain.setData(pdman, dstdfp.fTextureDomain, texture);
Brian Salomon0bbecb22016-11-17 11:38:22 -0500463 float iw = 1.f / texture->width();
464 float ih = 1.f / texture->height();
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400465 float scaleAndTransData[4] = {
466 iw, ih,
467 -dstdfp.fDeviceSpaceOffset.fX * iw, -dstdfp.fDeviceSpaceOffset.fY * ih
468 };
Brian Salomon0bbecb22016-11-17 11:38:22 -0500469 if (texture->origin() == kBottomLeft_GrSurfaceOrigin) {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400470 scaleAndTransData[1] = -scaleAndTransData[1];
471 scaleAndTransData[3] = 1 - scaleAndTransData[3];
472 }
473 pdman.set4fv(fScaleAndTranslateUni, 1, scaleAndTransData);
474 }
475
476 private:
477 GrTextureDomain::GLDomain fGLDomain;
478 UniformHandle fScaleAndTranslateUni;
479 };
480
481 return new GLSLProcessor;
482}
483
484bool GrDeviceSpaceTextureDecalFragmentProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
485 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
486 fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
Brian Salomondb4183d2016-11-17 12:48:40 -0500487 return dstdfp.fTextureSampler.texture() == fTextureSampler.texture() &&
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400488 dstdfp.fDeviceSpaceOffset == fDeviceSpaceOffset &&
489 dstdfp.fTextureDomain == fTextureDomain;
490}
491
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400492///////////////////////////////////////////////////////////////////////////////
493
494GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDeviceSpaceTextureDecalFragmentProcessor);
495
Hal Canary6f6961e2017-01-31 13:50:44 -0500496#if GR_TEST_UTILS
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400497sk_sp<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::TestCreate(
498 GrProcessorTestData* d) {
499 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
500 : GrProcessorUnitTest::kAlphaTextureIdx;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500501 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400502 SkIRect subset;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500503 subset.fLeft = d->fRandom->nextULessThan(proxy->width() - 1);
504 subset.fRight = d->fRandom->nextRangeU(subset.fLeft, proxy->width());
505 subset.fTop = d->fRandom->nextULessThan(proxy->height() - 1);
506 subset.fBottom = d->fRandom->nextRangeU(subset.fTop, proxy->height());
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400507 SkIPoint pt;
508 pt.fX = d->fRandom->nextULessThan(2048);
509 pt.fY = d->fRandom->nextULessThan(2048);
Robert Phillips40fd7c92017-01-30 08:06:27 -0500510 return GrDeviceSpaceTextureDecalFragmentProcessor::Make(d->context(),
511 std::move(proxy), subset, pt);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000512}
Hal Canary6f6961e2017-01-31 13:50:44 -0500513#endif