blob: 58707f5744f6173f35c45ca46d0cdd1f2690cd30 [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"
egdaniel605dd0f2014-11-12 08:35:25 -080011#include "GrInvariantOutput.h"
Brian Salomon94efbf52016-11-29 13:43:05 -050012#include "GrShaderCaps.h"
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000013#include "GrSimpleTextureEffect.h"
Robert Phillips40fd7c92017-01-30 08:06:27 -050014#include "GrSurfaceProxyPriv.h"
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000015#include "SkFloatingPoint.h"
Brian Osmanc4689632016-12-19 17:04:59 -050016#include "glsl/GrGLSLColorSpaceXformHelper.h"
egdaniel64c47282015-11-13 06:54:19 -080017#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel7ea439b2015-12-03 09:20:44 -080018#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniel018fb622015-10-28 07:26:40 -070019#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080020#include "glsl/GrGLSLShaderBuilder.h"
egdaniel7ea439b2015-12-03 09:20:44 -080021#include "glsl/GrGLSLUniformHandler.h"
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000022
Robert Phillips40fd7c92017-01-30 08:06:27 -050023static bool can_ignore_rect(GrSurfaceProxy* proxy, const SkRect& domain) {
24 if (proxy->priv().isExact()) {
25 const SkIRect kFullRect = SkIRect::MakeWH(proxy->width(), proxy->height());
26
27 return domain.contains(kFullRect);
28 }
29
30 return false;
31}
32
Robert Phillipse98234f2017-01-09 14:23:59 -050033static bool can_ignore_rect(GrTexture* tex, const SkRect& domain) {
34 // This logic is relying on the instantiated size of 'tex'. In the deferred world it
35 // will have to change so this logic only fires for kExact texture proxies. This shouldn't
36 // change the actual behavior of Ganesh since shaders shouldn't be accessing pixels outside
37 // of the content rectangle.
38 const SkIRect kFullRect = SkIRect::MakeWH(tex->width(), tex->height());
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000039
Robert Phillipse98234f2017-01-09 14:23:59 -050040 return domain.contains(kFullRect);
41}
42
43GrTextureDomain::GrTextureDomain(GrTexture* tex, const SkRect& domain, Mode mode, int index)
Robert Phillips40fd7c92017-01-30 08:06:27 -050044 : fMode(mode)
45 , fIndex(index) {
Robert Phillipse98234f2017-01-09 14:23:59 -050046
47 if (kIgnore_Mode == fMode) {
48 return;
49 }
50
51 if (kClamp_Mode == mode && can_ignore_rect(tex, domain)) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000052 fMode = kIgnore_Mode;
Robert Phillipse98234f2017-01-09 14:23:59 -050053 return;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000054 }
55
Robert Phillipse98234f2017-01-09 14:23:59 -050056 const SkRect kFullRect = SkRect::MakeIWH(tex->width(), tex->height());
57
58 // We don't currently handle domains that are empty or don't intersect the texture.
59 // It is OK if the domain rect is a line or point, but it should not be inverted. We do not
60 // handle rects that do not intersect the [0..1]x[0..1] rect.
61 SkASSERT(domain.fLeft <= domain.fRight);
62 SkASSERT(domain.fTop <= domain.fBottom);
63 fDomain.fLeft = SkScalarPin(domain.fLeft, 0.0f, kFullRect.fRight);
64 fDomain.fRight = SkScalarPin(domain.fRight, fDomain.fLeft, kFullRect.fRight);
65 fDomain.fTop = SkScalarPin(domain.fTop, 0.0f, kFullRect.fBottom);
66 fDomain.fBottom = SkScalarPin(domain.fBottom, fDomain.fTop, kFullRect.fBottom);
67 SkASSERT(fDomain.fLeft <= fDomain.fRight);
68 SkASSERT(fDomain.fTop <= fDomain.fBottom);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000069}
70
Robert Phillips40fd7c92017-01-30 08:06:27 -050071GrTextureDomain::GrTextureDomain(GrTextureProxy* proxy, const SkRect& domain, Mode mode, int index)
72 : fMode(mode)
73 , fIndex(index) {
74
75 if (kIgnore_Mode == fMode) {
76 return;
77 }
78
79 if (kClamp_Mode == mode && can_ignore_rect(proxy, domain)) {
80 fMode = kIgnore_Mode;
81 return;
82 }
83
84 const SkRect kFullRect = SkRect::MakeIWH(proxy->width(), proxy->height());
85
86 // We don't currently handle domains that are empty or don't intersect the texture.
87 // It is OK if the domain rect is a line or point, but it should not be inverted. We do not
88 // handle rects that do not intersect the [0..1]x[0..1] rect.
89 SkASSERT(domain.fLeft <= domain.fRight);
90 SkASSERT(domain.fTop <= domain.fBottom);
91 fDomain.fLeft = SkScalarPin(domain.fLeft, 0.0f, kFullRect.fRight);
92 fDomain.fRight = SkScalarPin(domain.fRight, fDomain.fLeft, kFullRect.fRight);
93 fDomain.fTop = SkScalarPin(domain.fTop, 0.0f, kFullRect.fBottom);
94 fDomain.fBottom = SkScalarPin(domain.fBottom, fDomain.fTop, kFullRect.fBottom);
95 SkASSERT(fDomain.fLeft <= fDomain.fRight);
96 SkASSERT(fDomain.fTop <= fDomain.fBottom);
97}
98
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000099//////////////////////////////////////////////////////////////////////////////
100
egdaniel2d721d32015-11-11 13:06:05 -0800101void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
egdaniel7ea439b2015-12-03 09:20:44 -0800102 GrGLSLUniformHandler* uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500103 const GrShaderCaps* shaderCaps,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000104 const GrTextureDomain& textureDomain,
105 const char* outColor,
106 const SkString& inCoords,
egdaniel09aa1fc2016-04-20 07:09:46 -0700107 GrGLSLFragmentProcessor::SamplerHandle sampler,
Brian Osmanc4689632016-12-19 17:04:59 -0500108 const char* inModulateColor,
109 GrGLSLColorSpaceXformHelper* colorXformHelper) {
reed@google.comd7b1af62013-12-09 20:31:50 +0000110 SkASSERT((Mode)-1 == fMode || textureDomain.mode() == fMode);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000111 SkDEBUGCODE(fMode = textureDomain.mode();)
112
joshualitt5ae5fc52014-07-29 12:59:27 -0700113 if (textureDomain.mode() != kIgnore_Mode && !fDomainUni.isValid()) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000114 const char* name;
115 SkString uniName("TexDom");
116 if (textureDomain.fIndex >= 0) {
117 uniName.appendS32(textureDomain.fIndex);
118 }
cdalton5e58cee2016-02-11 12:49:47 -0800119 fDomainUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800120 kVec4f_GrSLType, kDefault_GrSLPrecision,
121 uniName.c_str(), &name);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000122 fDomainName = name;
123 }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000124
joshualitt5ae5fc52014-07-29 12:59:27 -0700125 switch (textureDomain.mode()) {
126 case kIgnore_Mode: {
jvanverth3fc65602015-07-22 08:41:51 -0700127 builder->codeAppendf("%s = ", outColor);
Brian Osmanc4689632016-12-19 17:04:59 -0500128 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
129 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700130 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700131 break;
132 }
133 case kClamp_Mode: {
134 SkString clampedCoords;
jvanverth3fc65602015-07-22 08:41:51 -0700135 clampedCoords.appendf("clamp(%s, %s.xy, %s.zw)",
joshualitt5ae5fc52014-07-29 12:59:27 -0700136 inCoords.c_str(), fDomainName.c_str(), fDomainName.c_str());
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000137
jvanverth3fc65602015-07-22 08:41:51 -0700138 builder->codeAppendf("%s = ", outColor);
Brian Osmanc4689632016-12-19 17:04:59 -0500139 builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
140 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700141 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700142 break;
143 }
144 case kDecal_Mode: {
145 // Add a block since we're going to declare variables.
egdaniel2d721d32015-11-11 13:06:05 -0800146 GrGLSLShaderBuilder::ShaderBlock block(builder);
joshualitt5ae5fc52014-07-29 12:59:27 -0700147
148 const char* domain = fDomainName.c_str();
Brian Salomon1edc5b92016-11-29 13:43:46 -0500149 if (!shaderCaps->canUseAnyFunctionInShader()) {
joshualitt5ae5fc52014-07-29 12:59:27 -0700150 // On the NexusS and GalaxyNexus, the other path (with the 'any'
151 // call) causes the compilation error "Calls to any function that
152 // may require a gradient calculation inside a conditional block
153 // may return undefined results". This appears to be an issue with
154 // the 'any' call since even the simple "result=black; if (any())
155 // result=white;" code fails to compile.
jvanverth3fc65602015-07-22 08:41:51 -0700156 builder->codeAppend("vec4 outside = vec4(0.0, 0.0, 0.0, 0.0);");
157 builder->codeAppend("vec4 inside = ");
Brian Osmanc4689632016-12-19 17:04:59 -0500158 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
159 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700160 builder->codeAppend(";");
halcanary9d524f22016-03-29 09:03:52 -0700161
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500162 builder->codeAppendf("highp float x = (%s).x;", inCoords.c_str());
163 builder->codeAppendf("highp float y = (%s).y;", inCoords.c_str());
joshualitt5ae5fc52014-07-29 12:59:27 -0700164
jvanverth3fc65602015-07-22 08:41:51 -0700165 builder->codeAppendf("x = abs(2.0*(x - %s.x)/(%s.z - %s.x) - 1.0);",
166 domain, domain, domain);
167 builder->codeAppendf("y = abs(2.0*(y - %s.y)/(%s.w - %s.y) - 1.0);",
168 domain, domain, domain);
169 builder->codeAppend("float blend = step(1.0, max(x, y));");
170 builder->codeAppendf("%s = mix(inside, outside, blend);", outColor);
joshualitt5ae5fc52014-07-29 12:59:27 -0700171 } else {
jvanverth3fc65602015-07-22 08:41:51 -0700172 builder->codeAppend("bvec4 outside;\n");
173 builder->codeAppendf("outside.xy = lessThan(%s, %s.xy);", inCoords.c_str(),
joshualitt5ae5fc52014-07-29 12:59:27 -0700174 domain);
jvanverth3fc65602015-07-22 08:41:51 -0700175 builder->codeAppendf("outside.zw = greaterThan(%s, %s.zw);", inCoords.c_str(),
joshualitt5ae5fc52014-07-29 12:59:27 -0700176 domain);
jvanverth3fc65602015-07-22 08:41:51 -0700177 builder->codeAppendf("%s = any(outside) ? vec4(0.0, 0.0, 0.0, 0.0) : ",
joshualitt5ae5fc52014-07-29 12:59:27 -0700178 outColor);
Brian Osmanc4689632016-12-19 17:04:59 -0500179 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
180 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700181 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700182 }
183 break;
184 }
185 case kRepeat_Mode: {
186 SkString clampedCoords;
jvanverth3fc65602015-07-22 08:41:51 -0700187 clampedCoords.printf("mod(%s - %s.xy, %s.zw - %s.xy) + %s.xy",
joshualitt5ae5fc52014-07-29 12:59:27 -0700188 inCoords.c_str(), fDomainName.c_str(), fDomainName.c_str(),
189 fDomainName.c_str(), fDomainName.c_str());
190
jvanverth3fc65602015-07-22 08:41:51 -0700191 builder->codeAppendf("%s = ", outColor);
Brian Osmanc4689632016-12-19 17:04:59 -0500192 builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
193 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700194 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700195 break;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000196 }
197 }
198}
199
egdaniel018fb622015-10-28 07:26:40 -0700200void GrTextureDomain::GLDomain::setData(const GrGLSLProgramDataManager& pdman,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000201 const GrTextureDomain& textureDomain,
Robert Phillipse98234f2017-01-09 14:23:59 -0500202 GrTexture* tex) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000203 SkASSERT(textureDomain.mode() == fMode);
204 if (kIgnore_Mode != textureDomain.mode()) {
Robert Phillipse98234f2017-01-09 14:23:59 -0500205 SkScalar wInv = SK_Scalar1 / tex->width();
206 SkScalar hInv = SK_Scalar1 / tex->height();
207
egdaniel018fb622015-10-28 07:26:40 -0700208 float values[kPrevDomainCount] = {
Robert Phillipse98234f2017-01-09 14:23:59 -0500209 SkScalarToFloat(textureDomain.domain().fLeft * wInv),
210 SkScalarToFloat(textureDomain.domain().fTop * hInv),
211 SkScalarToFloat(textureDomain.domain().fRight * wInv),
212 SkScalarToFloat(textureDomain.domain().fBottom * hInv)
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000213 };
Robert Phillipse98234f2017-01-09 14:23:59 -0500214
215 SkASSERT(values[0] >= 0.0f && values[0] <= 1.0f);
216 SkASSERT(values[1] >= 0.0f && values[1] <= 1.0f);
217 SkASSERT(values[2] >= 0.0f && values[2] <= 1.0f);
218 SkASSERT(values[3] >= 0.0f && values[3] <= 1.0f);
219
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000220 // vertical flip if necessary
Robert Phillipse98234f2017-01-09 14:23:59 -0500221 if (kBottomLeft_GrSurfaceOrigin == tex->origin()) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000222 values[1] = 1.0f - values[1];
223 values[3] = 1.0f - values[3];
224 // The top and bottom were just flipped, so correct the ordering
225 // of elements so that values = (l, t, r, b).
226 SkTSwap(values[1], values[3]);
227 }
egdaniel018fb622015-10-28 07:26:40 -0700228 if (0 != memcmp(values, fPrevDomain, kPrevDomainCount * sizeof(float))) {
kkinnunen7510b222014-07-30 00:04:16 -0700229 pdman.set4fv(fDomainUni, 1, values);
egdaniel018fb622015-10-28 07:26:40 -0700230 memcpy(fPrevDomain, values, kPrevDomainCount * sizeof(float));
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000231 }
232 }
233}
234
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000235///////////////////////////////////////////////////////////////////////////////
bungeman06ca8ec2016-06-09 08:01:03 -0700236sk_sp<GrFragmentProcessor> GrTextureDomainEffect::Make(GrTexture* texture,
brianosman54f30c12016-07-18 10:53:52 -0700237 sk_sp<GrColorSpaceXform> colorSpaceXform,
bungeman06ca8ec2016-06-09 08:01:03 -0700238 const SkMatrix& matrix,
239 const SkRect& domain,
240 GrTextureDomain::Mode mode,
Brian Salomon514baff2016-11-17 15:17:07 -0500241 GrSamplerParams::FilterMode filterMode) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000242 if (GrTextureDomain::kIgnore_Mode == mode ||
Robert Phillipse98234f2017-01-09 14:23:59 -0500243 (GrTextureDomain::kClamp_Mode == mode && can_ignore_rect(texture, domain))) {
brianosman54f30c12016-07-18 10:53:52 -0700244 return GrSimpleTextureEffect::Make(texture, std::move(colorSpaceXform), matrix, filterMode);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000245 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700246 return sk_sp<GrFragmentProcessor>(
brianosman54f30c12016-07-18 10:53:52 -0700247 new GrTextureDomainEffect(texture, std::move(colorSpaceXform), matrix, domain, mode,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400248 filterMode));
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000249 }
250}
251
Brian Salomon587e08f2017-01-27 10:59:27 -0500252inline GrFragmentProcessor::OptimizationFlags GrTextureDomainEffect::OptFlags(
Robert Phillips40fd7c92017-01-30 08:06:27 -0500253 GrPixelConfig config, GrTextureDomain::Mode mode) {
254 if (mode == GrTextureDomain::kDecal_Mode || !GrPixelConfigIsOpaque(config)) {
Brian Salomon587e08f2017-01-27 10:59:27 -0500255 return GrFragmentProcessor::kModulatesInput_OptimizationFlag;
256 } else {
257 return GrFragmentProcessor::kModulatesInput_OptimizationFlag |
258 GrFragmentProcessor::kPreservesOpaqueInput_OptimizationFlag;
259 }
260}
261
bsalomon4a339522015-10-06 08:40:50 -0700262GrTextureDomainEffect::GrTextureDomainEffect(GrTexture* texture,
brianosman54f30c12016-07-18 10:53:52 -0700263 sk_sp<GrColorSpaceXform> colorSpaceXform,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000264 const SkMatrix& matrix,
265 const SkRect& domain,
266 GrTextureDomain::Mode mode,
Brian Salomon514baff2016-11-17 15:17:07 -0500267 GrSamplerParams::FilterMode filterMode)
Brian Salomon587e08f2017-01-27 10:59:27 -0500268 : GrSingleTextureEffect(texture, std::move(colorSpaceXform), matrix, filterMode,
Robert Phillips40fd7c92017-01-30 08:06:27 -0500269 OptFlags(texture->config(), mode))
Brian Salomon587e08f2017-01-27 10:59:27 -0500270 , fTextureDomain(texture, domain, mode) {
joshualitt5ae5fc52014-07-29 12:59:27 -0700271 SkASSERT(mode != GrTextureDomain::kRepeat_Mode ||
Brian Salomon514baff2016-11-17 15:17:07 -0500272 filterMode == GrSamplerParams::kNone_FilterMode);
joshualitteb2a6762014-12-04 11:35:33 -0800273 this->initClassID<GrTextureDomainEffect>();
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000274}
275
Robert Phillips40fd7c92017-01-30 08:06:27 -0500276sk_sp<GrFragmentProcessor> GrTextureDomainEffect::Make(GrContext* context,
277 sk_sp<GrTextureProxy> proxy,
278 sk_sp<GrColorSpaceXform> colorSpaceXform,
279 const SkMatrix& matrix,
280 const SkRect& domain,
281 GrTextureDomain::Mode mode,
282 GrSamplerParams::FilterMode filterMode) {
283 if (GrTextureDomain::kIgnore_Mode == mode ||
284 (GrTextureDomain::kClamp_Mode == mode && can_ignore_rect(proxy.get(), domain))) {
285 return GrSimpleTextureEffect::Make(context, std::move(proxy), std::move(colorSpaceXform),
286 matrix, filterMode);
287 } else {
288 return sk_sp<GrFragmentProcessor>(
289 new GrTextureDomainEffect(context, std::move(proxy), std::move(colorSpaceXform),
290 matrix, domain, mode, filterMode));
291 }
292}
293
294GrTextureDomainEffect::GrTextureDomainEffect(GrContext* context,
295 sk_sp<GrTextureProxy> proxy,
296 sk_sp<GrColorSpaceXform> colorSpaceXform,
297 const SkMatrix& matrix,
298 const SkRect& domain,
299 GrTextureDomain::Mode mode,
300 GrSamplerParams::FilterMode filterMode)
301 : GrSingleTextureEffect(context, OptFlags(proxy->config(), mode), proxy,
302 std::move(colorSpaceXform), matrix, filterMode)
303 , fTextureDomain(proxy.get(), domain, mode) {
304 SkASSERT(mode != GrTextureDomain::kRepeat_Mode ||
305 filterMode == GrSamplerParams::kNone_FilterMode);
306 this->initClassID<GrTextureDomainEffect>();
307}
308
Brian Salomon94efbf52016-11-29 13:43:05 -0500309void GrTextureDomainEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800310 GrProcessorKeyBuilder* b) const {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400311 b->add32(GrTextureDomain::GLDomain::DomainKey(fTextureDomain));
Brian Osman70826d72016-12-20 15:06:18 -0500312 b->add32(GrColorSpaceXform::XformKey(this->colorSpaceXform()));
joshualitteb2a6762014-12-04 11:35:33 -0800313}
314
egdaniel57d3b032015-11-13 11:57:27 -0800315GrGLSLFragmentProcessor* GrTextureDomainEffect::onCreateGLSLInstance() const {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400316 class GLSLProcessor : public GrGLSLFragmentProcessor {
317 public:
318 void emitCode(EmitArgs& args) override {
319 const GrTextureDomainEffect& tde = args.fFp.cast<GrTextureDomainEffect>();
320 const GrTextureDomain& domain = tde.fTextureDomain;
321
322 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
323 SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
Brian Osmanc4689632016-12-19 17:04:59 -0500324
325 GrGLSLColorSpaceXformHelper colorSpaceHelper(args.fUniformHandler,
326 tde.colorSpaceXform(),
327 &fColorSpaceXformUni);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400328 fGLDomain.sampleTexture(fragBuilder,
329 args.fUniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500330 args.fShaderCaps,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400331 domain,
332 args.fOutputColor,
333 coords2D,
334 args.fTexSamplers[0],
Brian Osmanc4689632016-12-19 17:04:59 -0500335 args.fInputColor,
336 &colorSpaceHelper);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400337 }
338
339 protected:
340 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& fp) override {
341 const GrTextureDomainEffect& tde = fp.cast<GrTextureDomainEffect>();
342 const GrTextureDomain& domain = tde.fTextureDomain;
Robert Phillipse98234f2017-01-09 14:23:59 -0500343 fGLDomain.setData(pdman, domain, tde.textureSampler(0).texture());
Brian Osmanc4689632016-12-19 17:04:59 -0500344 if (SkToBool(tde.colorSpaceXform())) {
345 pdman.setSkMatrix44(fColorSpaceXformUni, tde.colorSpaceXform()->srcToDst());
346 }
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400347 }
348
349 private:
350 GrTextureDomain::GLDomain fGLDomain;
Brian Osmanc4689632016-12-19 17:04:59 -0500351 UniformHandle fColorSpaceXformUni;
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400352 };
353
354 return new GLSLProcessor;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000355}
356
bsalomon0e08fc12014-10-15 08:19:04 -0700357bool GrTextureDomainEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
joshualitt49586be2014-09-16 08:21:41 -0700358 const GrTextureDomainEffect& s = sBase.cast<GrTextureDomainEffect>();
Brian Salomona7c4c292016-11-17 12:47:06 -0500359 return this->fTextureDomain == s.fTextureDomain;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000360}
361
egdaniel605dd0f2014-11-12 08:35:25 -0800362void GrTextureDomainEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400363 if (GrTextureDomain::kDecal_Mode == fTextureDomain.mode()) {
Brian Salomondb4183d2016-11-17 12:48:40 -0500364 if (GrPixelConfigIsAlphaOnly(this->textureSampler(0).texture()->config())) {
joshualitt56995b52014-12-11 15:44:02 -0800365 inout->mulByUnknownSingleComponent();
egdanielf8449ba2014-11-25 10:24:56 -0800366 } else {
joshualitt56995b52014-12-11 15:44:02 -0800367 inout->mulByUnknownFourComponents();
egdanielf8449ba2014-11-25 10:24:56 -0800368 }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000369 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700370 this->updateInvariantOutputForModulation(inout);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000371 }
372}
373
374///////////////////////////////////////////////////////////////////////////////
375
joshualittb0a8a372014-09-23 09:50:21 -0700376GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrTextureDomainEffect);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000377
Hal Canary6f6961e2017-01-31 13:50:44 -0500378#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700379sk_sp<GrFragmentProcessor> GrTextureDomainEffect::TestCreate(GrProcessorTestData* d) {
Robert Phillips40fd7c92017-01-30 08:06:27 -0500380 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
381 : GrProcessorUnitTest::kAlphaTextureIdx;
382 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000383 SkRect domain;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500384 domain.fLeft = d->fRandom->nextRangeScalar(0, proxy->width());
385 domain.fRight = d->fRandom->nextRangeScalar(domain.fLeft, proxy->width());
386 domain.fTop = d->fRandom->nextRangeScalar(0, proxy->height());
387 domain.fBottom = d->fRandom->nextRangeScalar(domain.fTop, proxy->height());
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000388 GrTextureDomain::Mode mode =
joshualitt0067ff52015-07-08 14:26:19 -0700389 (GrTextureDomain::Mode) d->fRandom->nextULessThan(GrTextureDomain::kModeCount);
390 const SkMatrix& matrix = GrTest::TestMatrix(d->fRandom);
391 bool bilerp = mode != GrTextureDomain::kRepeat_Mode ? d->fRandom->nextBool() : false;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500392 sk_sp<GrColorSpaceXform> colorSpaceXform = GrTest::TestColorXform(d->fRandom);
393 return GrTextureDomainEffect::Make(d->context(),
394 std::move(proxy),
395 std::move(colorSpaceXform),
396 matrix,
397 domain,
398 mode,
399 bilerp ? GrSamplerParams::kBilerp_FilterMode
400 : GrSamplerParams::kNone_FilterMode);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400401}
Hal Canary6f6961e2017-01-31 13:50:44 -0500402#endif
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400403
404///////////////////////////////////////////////////////////////////////////////
405
406sk_sp<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::Make(GrTexture* texture,
407 const SkIRect& subset, const SkIPoint& deviceSpaceOffset) {
408 return sk_sp<GrFragmentProcessor>(new GrDeviceSpaceTextureDecalFragmentProcessor(
409 texture, subset, deviceSpaceOffset));
410}
411
412GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
413 GrTexture* texture, const SkIRect& subset, const SkIPoint& deviceSpaceOffset)
Brian Salomon587e08f2017-01-27 10:59:27 -0500414 : INHERITED(kModulatesInput_OptimizationFlag)
415 , fTextureSampler(texture, GrSamplerParams::ClampNoFilter())
Robert Phillipse98234f2017-01-09 14:23:59 -0500416 , fTextureDomain(texture, GrTextureDomain::MakeTexelDomain(subset),
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400417 GrTextureDomain::kDecal_Mode) {
Brian Salomon0bbecb22016-11-17 11:38:22 -0500418 this->addTextureSampler(&fTextureSampler);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400419 fDeviceSpaceOffset.fX = deviceSpaceOffset.fX - subset.fLeft;
420 fDeviceSpaceOffset.fY = deviceSpaceOffset.fY - subset.fTop;
421 this->initClassID<GrDeviceSpaceTextureDecalFragmentProcessor>();
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400422}
423
Robert Phillips40fd7c92017-01-30 08:06:27 -0500424sk_sp<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::Make(
425 GrContext* context,
426 sk_sp<GrTextureProxy> proxy,
427 const SkIRect& subset,
428 const SkIPoint& deviceSpaceOffset) {
429 return sk_sp<GrFragmentProcessor>(new GrDeviceSpaceTextureDecalFragmentProcessor(
430 context, std::move(proxy), subset, deviceSpaceOffset));
431}
432
433GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
434 GrContext* context,
435 sk_sp<GrTextureProxy> proxy,
436 const SkIRect& subset,
437 const SkIPoint& deviceSpaceOffset)
438 : INHERITED(kModulatesInput_OptimizationFlag)
439 , fTextureSampler(context->textureProvider(), proxy, GrSamplerParams::ClampNoFilter())
440 , fTextureDomain(proxy.get(), GrTextureDomain::MakeTexelDomain(subset),
441 GrTextureDomain::kDecal_Mode) {
442 this->addTextureSampler(&fTextureSampler);
443 fDeviceSpaceOffset.fX = deviceSpaceOffset.fX - subset.fLeft;
444 fDeviceSpaceOffset.fY = deviceSpaceOffset.fY - subset.fTop;
445 this->initClassID<GrDeviceSpaceTextureDecalFragmentProcessor>();
446}
447
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400448GrGLSLFragmentProcessor* GrDeviceSpaceTextureDecalFragmentProcessor::onCreateGLSLInstance() const {
449 class GLSLProcessor : public GrGLSLFragmentProcessor {
450 public:
451 void emitCode(EmitArgs& args) override {
452 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
453 args.fFp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
454 const char* scaleAndTranslateName;
455 fScaleAndTranslateUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
456 kVec4f_GrSLType,
457 kDefault_GrSLPrecision,
458 "scaleAndTranslate",
459 &scaleAndTranslateName);
Ethan Nicholasde4d3012017-01-19 16:58:02 -0500460 args.fFragBuilder->codeAppendf("vec2 coords = sk_FragCoord.xy * %s.xy + %s.zw;",
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400461 scaleAndTranslateName, scaleAndTranslateName);
462 fGLDomain.sampleTexture(args.fFragBuilder,
463 args.fUniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500464 args.fShaderCaps,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400465 dstdfp.fTextureDomain,
466 args.fOutputColor,
467 SkString("coords"),
468 args.fTexSamplers[0],
469 args.fInputColor);
470 }
471
472 protected:
473 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& fp) override {
474 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
475 fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
Brian Salomondb4183d2016-11-17 12:48:40 -0500476 GrTexture* texture = dstdfp.textureSampler(0).texture();
Robert Phillipse98234f2017-01-09 14:23:59 -0500477 fGLDomain.setData(pdman, dstdfp.fTextureDomain, texture);
Brian Salomon0bbecb22016-11-17 11:38:22 -0500478 float iw = 1.f / texture->width();
479 float ih = 1.f / texture->height();
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400480 float scaleAndTransData[4] = {
481 iw, ih,
482 -dstdfp.fDeviceSpaceOffset.fX * iw, -dstdfp.fDeviceSpaceOffset.fY * ih
483 };
Brian Salomon0bbecb22016-11-17 11:38:22 -0500484 if (texture->origin() == kBottomLeft_GrSurfaceOrigin) {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400485 scaleAndTransData[1] = -scaleAndTransData[1];
486 scaleAndTransData[3] = 1 - scaleAndTransData[3];
487 }
488 pdman.set4fv(fScaleAndTranslateUni, 1, scaleAndTransData);
489 }
490
491 private:
492 GrTextureDomain::GLDomain fGLDomain;
493 UniformHandle fScaleAndTranslateUni;
494 };
495
496 return new GLSLProcessor;
497}
498
499bool GrDeviceSpaceTextureDecalFragmentProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
500 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
501 fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
Brian Salomondb4183d2016-11-17 12:48:40 -0500502 return dstdfp.fTextureSampler.texture() == fTextureSampler.texture() &&
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400503 dstdfp.fDeviceSpaceOffset == fDeviceSpaceOffset &&
504 dstdfp.fTextureDomain == fTextureDomain;
505}
506
507void GrDeviceSpaceTextureDecalFragmentProcessor::onComputeInvariantOutput(
508 GrInvariantOutput* inout) const {
Brian Salomondb4183d2016-11-17 12:48:40 -0500509 if (GrPixelConfigIsAlphaOnly(this->textureSampler(0).texture()->config())) {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400510 inout->mulByUnknownSingleComponent();
511 } else {
512 inout->mulByUnknownFourComponents();
513 }
514}
515
516///////////////////////////////////////////////////////////////////////////////
517
518GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDeviceSpaceTextureDecalFragmentProcessor);
519
Hal Canary6f6961e2017-01-31 13:50:44 -0500520#if GR_TEST_UTILS
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400521sk_sp<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::TestCreate(
522 GrProcessorTestData* d) {
523 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
524 : GrProcessorUnitTest::kAlphaTextureIdx;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500525 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400526 SkIRect subset;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500527 subset.fLeft = d->fRandom->nextULessThan(proxy->width() - 1);
528 subset.fRight = d->fRandom->nextRangeU(subset.fLeft, proxy->width());
529 subset.fTop = d->fRandom->nextULessThan(proxy->height() - 1);
530 subset.fBottom = d->fRandom->nextRangeU(subset.fTop, proxy->height());
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400531 SkIPoint pt;
532 pt.fX = d->fRandom->nextULessThan(2048);
533 pt.fY = d->fRandom->nextULessThan(2048);
Robert Phillips40fd7c92017-01-30 08:06:27 -0500534 return GrDeviceSpaceTextureDecalFragmentProcessor::Make(d->context(),
535 std::move(proxy), subset, pt);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000536}
Hal Canary6f6961e2017-01-31 13:50:44 -0500537#endif