blob: d6872e1c2e8ae56c5ae8de8e0b2360cc25c6d411 [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"
egdaniel605dd0f2014-11-12 08:35:25 -08009#include "GrInvariantOutput.h"
Brian Salomon94efbf52016-11-29 13:43:05 -050010#include "GrShaderCaps.h"
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000011#include "GrSimpleTextureEffect.h"
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000012#include "SkFloatingPoint.h"
Brian Osmanc4689632016-12-19 17:04:59 -050013#include "glsl/GrGLSLColorSpaceXformHelper.h"
egdaniel64c47282015-11-13 06:54:19 -080014#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel7ea439b2015-12-03 09:20:44 -080015#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniel018fb622015-10-28 07:26:40 -070016#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080017#include "glsl/GrGLSLShaderBuilder.h"
egdaniel7ea439b2015-12-03 09:20:44 -080018#include "glsl/GrGLSLUniformHandler.h"
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000019
Robert Phillipse98234f2017-01-09 14:23:59 -050020static bool can_ignore_rect(GrTexture* tex, const SkRect& domain) {
21 // This logic is relying on the instantiated size of 'tex'. In the deferred world it
22 // will have to change so this logic only fires for kExact texture proxies. This shouldn't
23 // change the actual behavior of Ganesh since shaders shouldn't be accessing pixels outside
24 // of the content rectangle.
25 const SkIRect kFullRect = SkIRect::MakeWH(tex->width(), tex->height());
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000026
Robert Phillipse98234f2017-01-09 14:23:59 -050027 return domain.contains(kFullRect);
28}
29
30GrTextureDomain::GrTextureDomain(GrTexture* tex, const SkRect& domain, Mode mode, int index)
31 : fMode(mode), fIndex(index) {
32
33 if (kIgnore_Mode == fMode) {
34 return;
35 }
36
37 if (kClamp_Mode == mode && can_ignore_rect(tex, domain)) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000038 fMode = kIgnore_Mode;
Robert Phillipse98234f2017-01-09 14:23:59 -050039 return;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000040 }
41
Robert Phillipse98234f2017-01-09 14:23:59 -050042 const SkRect kFullRect = SkRect::MakeIWH(tex->width(), tex->height());
43
44 // We don't currently handle domains that are empty or don't intersect the texture.
45 // It is OK if the domain rect is a line or point, but it should not be inverted. We do not
46 // handle rects that do not intersect the [0..1]x[0..1] rect.
47 SkASSERT(domain.fLeft <= domain.fRight);
48 SkASSERT(domain.fTop <= domain.fBottom);
49 fDomain.fLeft = SkScalarPin(domain.fLeft, 0.0f, kFullRect.fRight);
50 fDomain.fRight = SkScalarPin(domain.fRight, fDomain.fLeft, kFullRect.fRight);
51 fDomain.fTop = SkScalarPin(domain.fTop, 0.0f, kFullRect.fBottom);
52 fDomain.fBottom = SkScalarPin(domain.fBottom, fDomain.fTop, kFullRect.fBottom);
53 SkASSERT(fDomain.fLeft <= fDomain.fRight);
54 SkASSERT(fDomain.fTop <= fDomain.fBottom);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000055}
56
57//////////////////////////////////////////////////////////////////////////////
58
egdaniel2d721d32015-11-11 13:06:05 -080059void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
egdaniel7ea439b2015-12-03 09:20:44 -080060 GrGLSLUniformHandler* uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -050061 const GrShaderCaps* shaderCaps,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000062 const GrTextureDomain& textureDomain,
63 const char* outColor,
64 const SkString& inCoords,
egdaniel09aa1fc2016-04-20 07:09:46 -070065 GrGLSLFragmentProcessor::SamplerHandle sampler,
Brian Osmanc4689632016-12-19 17:04:59 -050066 const char* inModulateColor,
67 GrGLSLColorSpaceXformHelper* colorXformHelper) {
reed@google.comd7b1af62013-12-09 20:31:50 +000068 SkASSERT((Mode)-1 == fMode || textureDomain.mode() == fMode);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000069 SkDEBUGCODE(fMode = textureDomain.mode();)
70
joshualitt5ae5fc52014-07-29 12:59:27 -070071 if (textureDomain.mode() != kIgnore_Mode && !fDomainUni.isValid()) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000072 const char* name;
73 SkString uniName("TexDom");
74 if (textureDomain.fIndex >= 0) {
75 uniName.appendS32(textureDomain.fIndex);
76 }
cdalton5e58cee2016-02-11 12:49:47 -080077 fDomainUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -080078 kVec4f_GrSLType, kDefault_GrSLPrecision,
79 uniName.c_str(), &name);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000080 fDomainName = name;
81 }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000082
joshualitt5ae5fc52014-07-29 12:59:27 -070083 switch (textureDomain.mode()) {
84 case kIgnore_Mode: {
jvanverth3fc65602015-07-22 08:41:51 -070085 builder->codeAppendf("%s = ", outColor);
Brian Osmanc4689632016-12-19 17:04:59 -050086 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
87 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -070088 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -070089 break;
90 }
91 case kClamp_Mode: {
92 SkString clampedCoords;
jvanverth3fc65602015-07-22 08:41:51 -070093 clampedCoords.appendf("clamp(%s, %s.xy, %s.zw)",
joshualitt5ae5fc52014-07-29 12:59:27 -070094 inCoords.c_str(), fDomainName.c_str(), fDomainName.c_str());
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000095
jvanverth3fc65602015-07-22 08:41:51 -070096 builder->codeAppendf("%s = ", outColor);
Brian Osmanc4689632016-12-19 17:04:59 -050097 builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
98 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -070099 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700100 break;
101 }
102 case kDecal_Mode: {
103 // Add a block since we're going to declare variables.
egdaniel2d721d32015-11-11 13:06:05 -0800104 GrGLSLShaderBuilder::ShaderBlock block(builder);
joshualitt5ae5fc52014-07-29 12:59:27 -0700105
106 const char* domain = fDomainName.c_str();
Brian Salomon1edc5b92016-11-29 13:43:46 -0500107 if (!shaderCaps->canUseAnyFunctionInShader()) {
joshualitt5ae5fc52014-07-29 12:59:27 -0700108 // On the NexusS and GalaxyNexus, the other path (with the 'any'
109 // call) causes the compilation error "Calls to any function that
110 // may require a gradient calculation inside a conditional block
111 // may return undefined results". This appears to be an issue with
112 // the 'any' call since even the simple "result=black; if (any())
113 // result=white;" code fails to compile.
jvanverth3fc65602015-07-22 08:41:51 -0700114 builder->codeAppend("vec4 outside = vec4(0.0, 0.0, 0.0, 0.0);");
115 builder->codeAppend("vec4 inside = ");
Brian Osmanc4689632016-12-19 17:04:59 -0500116 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
117 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700118 builder->codeAppend(";");
halcanary9d524f22016-03-29 09:03:52 -0700119
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500120 builder->codeAppendf("highp float x = (%s).x;", inCoords.c_str());
121 builder->codeAppendf("highp float y = (%s).y;", inCoords.c_str());
joshualitt5ae5fc52014-07-29 12:59:27 -0700122
jvanverth3fc65602015-07-22 08:41:51 -0700123 builder->codeAppendf("x = abs(2.0*(x - %s.x)/(%s.z - %s.x) - 1.0);",
124 domain, domain, domain);
125 builder->codeAppendf("y = abs(2.0*(y - %s.y)/(%s.w - %s.y) - 1.0);",
126 domain, domain, domain);
127 builder->codeAppend("float blend = step(1.0, max(x, y));");
128 builder->codeAppendf("%s = mix(inside, outside, blend);", outColor);
joshualitt5ae5fc52014-07-29 12:59:27 -0700129 } else {
jvanverth3fc65602015-07-22 08:41:51 -0700130 builder->codeAppend("bvec4 outside;\n");
131 builder->codeAppendf("outside.xy = lessThan(%s, %s.xy);", inCoords.c_str(),
joshualitt5ae5fc52014-07-29 12:59:27 -0700132 domain);
jvanverth3fc65602015-07-22 08:41:51 -0700133 builder->codeAppendf("outside.zw = greaterThan(%s, %s.zw);", inCoords.c_str(),
joshualitt5ae5fc52014-07-29 12:59:27 -0700134 domain);
jvanverth3fc65602015-07-22 08:41:51 -0700135 builder->codeAppendf("%s = any(outside) ? vec4(0.0, 0.0, 0.0, 0.0) : ",
joshualitt5ae5fc52014-07-29 12:59:27 -0700136 outColor);
Brian Osmanc4689632016-12-19 17:04:59 -0500137 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
138 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700139 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700140 }
141 break;
142 }
143 case kRepeat_Mode: {
144 SkString clampedCoords;
jvanverth3fc65602015-07-22 08:41:51 -0700145 clampedCoords.printf("mod(%s - %s.xy, %s.zw - %s.xy) + %s.xy",
joshualitt5ae5fc52014-07-29 12:59:27 -0700146 inCoords.c_str(), fDomainName.c_str(), fDomainName.c_str(),
147 fDomainName.c_str(), fDomainName.c_str());
148
jvanverth3fc65602015-07-22 08:41:51 -0700149 builder->codeAppendf("%s = ", outColor);
Brian Osmanc4689632016-12-19 17:04:59 -0500150 builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
151 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700152 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700153 break;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000154 }
155 }
156}
157
egdaniel018fb622015-10-28 07:26:40 -0700158void GrTextureDomain::GLDomain::setData(const GrGLSLProgramDataManager& pdman,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000159 const GrTextureDomain& textureDomain,
Robert Phillipse98234f2017-01-09 14:23:59 -0500160 GrTexture* tex) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000161 SkASSERT(textureDomain.mode() == fMode);
162 if (kIgnore_Mode != textureDomain.mode()) {
Robert Phillipse98234f2017-01-09 14:23:59 -0500163 SkScalar wInv = SK_Scalar1 / tex->width();
164 SkScalar hInv = SK_Scalar1 / tex->height();
165
egdaniel018fb622015-10-28 07:26:40 -0700166 float values[kPrevDomainCount] = {
Robert Phillipse98234f2017-01-09 14:23:59 -0500167 SkScalarToFloat(textureDomain.domain().fLeft * wInv),
168 SkScalarToFloat(textureDomain.domain().fTop * hInv),
169 SkScalarToFloat(textureDomain.domain().fRight * wInv),
170 SkScalarToFloat(textureDomain.domain().fBottom * hInv)
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000171 };
Robert Phillipse98234f2017-01-09 14:23:59 -0500172
173 SkASSERT(values[0] >= 0.0f && values[0] <= 1.0f);
174 SkASSERT(values[1] >= 0.0f && values[1] <= 1.0f);
175 SkASSERT(values[2] >= 0.0f && values[2] <= 1.0f);
176 SkASSERT(values[3] >= 0.0f && values[3] <= 1.0f);
177
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000178 // vertical flip if necessary
Robert Phillipse98234f2017-01-09 14:23:59 -0500179 if (kBottomLeft_GrSurfaceOrigin == tex->origin()) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000180 values[1] = 1.0f - values[1];
181 values[3] = 1.0f - values[3];
182 // The top and bottom were just flipped, so correct the ordering
183 // of elements so that values = (l, t, r, b).
184 SkTSwap(values[1], values[3]);
185 }
egdaniel018fb622015-10-28 07:26:40 -0700186 if (0 != memcmp(values, fPrevDomain, kPrevDomainCount * sizeof(float))) {
kkinnunen7510b222014-07-30 00:04:16 -0700187 pdman.set4fv(fDomainUni, 1, values);
egdaniel018fb622015-10-28 07:26:40 -0700188 memcpy(fPrevDomain, values, kPrevDomainCount * sizeof(float));
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000189 }
190 }
191}
192
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000193///////////////////////////////////////////////////////////////////////////////
194
bungeman06ca8ec2016-06-09 08:01:03 -0700195sk_sp<GrFragmentProcessor> GrTextureDomainEffect::Make(GrTexture* texture,
brianosman54f30c12016-07-18 10:53:52 -0700196 sk_sp<GrColorSpaceXform> colorSpaceXform,
bungeman06ca8ec2016-06-09 08:01:03 -0700197 const SkMatrix& matrix,
198 const SkRect& domain,
199 GrTextureDomain::Mode mode,
Brian Salomon514baff2016-11-17 15:17:07 -0500200 GrSamplerParams::FilterMode filterMode) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000201 if (GrTextureDomain::kIgnore_Mode == mode ||
Robert Phillipse98234f2017-01-09 14:23:59 -0500202 (GrTextureDomain::kClamp_Mode == mode && can_ignore_rect(texture, domain))) {
brianosman54f30c12016-07-18 10:53:52 -0700203 return GrSimpleTextureEffect::Make(texture, std::move(colorSpaceXform), matrix, filterMode);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000204 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700205 return sk_sp<GrFragmentProcessor>(
brianosman54f30c12016-07-18 10:53:52 -0700206 new GrTextureDomainEffect(texture, std::move(colorSpaceXform), matrix, domain, mode,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400207 filterMode));
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000208 }
209}
210
bsalomon4a339522015-10-06 08:40:50 -0700211GrTextureDomainEffect::GrTextureDomainEffect(GrTexture* texture,
brianosman54f30c12016-07-18 10:53:52 -0700212 sk_sp<GrColorSpaceXform> colorSpaceXform,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000213 const SkMatrix& matrix,
214 const SkRect& domain,
215 GrTextureDomain::Mode mode,
Brian Salomon514baff2016-11-17 15:17:07 -0500216 GrSamplerParams::FilterMode filterMode)
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400217 : GrSingleTextureEffect(texture, std::move(colorSpaceXform), matrix, filterMode)
Robert Phillipse98234f2017-01-09 14:23:59 -0500218 , fTextureDomain(texture, domain, mode) {
joshualitt5ae5fc52014-07-29 12:59:27 -0700219 SkASSERT(mode != GrTextureDomain::kRepeat_Mode ||
Brian Salomon514baff2016-11-17 15:17:07 -0500220 filterMode == GrSamplerParams::kNone_FilterMode);
joshualitteb2a6762014-12-04 11:35:33 -0800221 this->initClassID<GrTextureDomainEffect>();
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000222}
223
Brian Salomon94efbf52016-11-29 13:43:05 -0500224void GrTextureDomainEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800225 GrProcessorKeyBuilder* b) const {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400226 b->add32(GrTextureDomain::GLDomain::DomainKey(fTextureDomain));
Brian Osman70826d72016-12-20 15:06:18 -0500227 b->add32(GrColorSpaceXform::XformKey(this->colorSpaceXform()));
joshualitteb2a6762014-12-04 11:35:33 -0800228}
229
egdaniel57d3b032015-11-13 11:57:27 -0800230GrGLSLFragmentProcessor* GrTextureDomainEffect::onCreateGLSLInstance() const {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400231 class GLSLProcessor : public GrGLSLFragmentProcessor {
232 public:
233 void emitCode(EmitArgs& args) override {
234 const GrTextureDomainEffect& tde = args.fFp.cast<GrTextureDomainEffect>();
235 const GrTextureDomain& domain = tde.fTextureDomain;
236
237 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
238 SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
Brian Osmanc4689632016-12-19 17:04:59 -0500239
240 GrGLSLColorSpaceXformHelper colorSpaceHelper(args.fUniformHandler,
241 tde.colorSpaceXform(),
242 &fColorSpaceXformUni);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400243 fGLDomain.sampleTexture(fragBuilder,
244 args.fUniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500245 args.fShaderCaps,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400246 domain,
247 args.fOutputColor,
248 coords2D,
249 args.fTexSamplers[0],
Brian Osmanc4689632016-12-19 17:04:59 -0500250 args.fInputColor,
251 &colorSpaceHelper);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400252 }
253
254 protected:
255 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& fp) override {
256 const GrTextureDomainEffect& tde = fp.cast<GrTextureDomainEffect>();
257 const GrTextureDomain& domain = tde.fTextureDomain;
Robert Phillipse98234f2017-01-09 14:23:59 -0500258 fGLDomain.setData(pdman, domain, tde.textureSampler(0).texture());
Brian Osmanc4689632016-12-19 17:04:59 -0500259 if (SkToBool(tde.colorSpaceXform())) {
260 pdman.setSkMatrix44(fColorSpaceXformUni, tde.colorSpaceXform()->srcToDst());
261 }
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400262 }
263
264 private:
265 GrTextureDomain::GLDomain fGLDomain;
Brian Osmanc4689632016-12-19 17:04:59 -0500266 UniformHandle fColorSpaceXformUni;
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400267 };
268
269 return new GLSLProcessor;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000270}
271
bsalomon0e08fc12014-10-15 08:19:04 -0700272bool GrTextureDomainEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
joshualitt49586be2014-09-16 08:21:41 -0700273 const GrTextureDomainEffect& s = sBase.cast<GrTextureDomainEffect>();
Brian Salomona7c4c292016-11-17 12:47:06 -0500274 return this->fTextureDomain == s.fTextureDomain;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000275}
276
egdaniel605dd0f2014-11-12 08:35:25 -0800277void GrTextureDomainEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400278 if (GrTextureDomain::kDecal_Mode == fTextureDomain.mode()) {
Brian Salomondb4183d2016-11-17 12:48:40 -0500279 if (GrPixelConfigIsAlphaOnly(this->textureSampler(0).texture()->config())) {
joshualitt56995b52014-12-11 15:44:02 -0800280 inout->mulByUnknownSingleComponent();
egdanielf8449ba2014-11-25 10:24:56 -0800281 } else {
joshualitt56995b52014-12-11 15:44:02 -0800282 inout->mulByUnknownFourComponents();
egdanielf8449ba2014-11-25 10:24:56 -0800283 }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000284 } else {
egdaniel1a8ecdf2014-10-03 06:24:12 -0700285 this->updateInvariantOutputForModulation(inout);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000286 }
287}
288
289///////////////////////////////////////////////////////////////////////////////
290
joshualittb0a8a372014-09-23 09:50:21 -0700291GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrTextureDomainEffect);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000292
bungeman06ca8ec2016-06-09 08:01:03 -0700293sk_sp<GrFragmentProcessor> GrTextureDomainEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700294 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
295 GrProcessorUnitTest::kAlphaTextureIdx;
Robert Phillipse98234f2017-01-09 14:23:59 -0500296 GrTexture* tex = d->fTextures[texIdx];
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000297 SkRect domain;
Robert Phillipse98234f2017-01-09 14:23:59 -0500298 domain.fLeft = d->fRandom->nextRangeScalar(0, tex->width());
299 domain.fRight = d->fRandom->nextRangeScalar(domain.fLeft, tex->width());
300 domain.fTop = d->fRandom->nextRangeScalar(0, tex->height());
301 domain.fBottom = d->fRandom->nextRangeScalar(domain.fTop, tex->height());
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000302 GrTextureDomain::Mode mode =
joshualitt0067ff52015-07-08 14:26:19 -0700303 (GrTextureDomain::Mode) d->fRandom->nextULessThan(GrTextureDomain::kModeCount);
304 const SkMatrix& matrix = GrTest::TestMatrix(d->fRandom);
305 bool bilerp = mode != GrTextureDomain::kRepeat_Mode ? d->fRandom->nextBool() : false;
Brian Osmane2f732f2016-10-03 14:23:50 -0400306 auto colorSpaceXform = GrTest::TestColorXform(d->fRandom);
bungeman06ca8ec2016-06-09 08:01:03 -0700307 return GrTextureDomainEffect::Make(
Robert Phillipse98234f2017-01-09 14:23:59 -0500308 tex,
Brian Osmane2f732f2016-10-03 14:23:50 -0400309 colorSpaceXform,
bsalomon0ba8c242015-10-07 09:20:28 -0700310 matrix,
311 domain,
312 mode,
Brian Salomon514baff2016-11-17 15:17:07 -0500313 bilerp ? GrSamplerParams::kBilerp_FilterMode : GrSamplerParams::kNone_FilterMode);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400314}
315
316///////////////////////////////////////////////////////////////////////////////
317
318sk_sp<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::Make(GrTexture* texture,
319 const SkIRect& subset, const SkIPoint& deviceSpaceOffset) {
320 return sk_sp<GrFragmentProcessor>(new GrDeviceSpaceTextureDecalFragmentProcessor(
321 texture, subset, deviceSpaceOffset));
322}
323
324GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
325 GrTexture* texture, const SkIRect& subset, const SkIPoint& deviceSpaceOffset)
Brian Salomon514baff2016-11-17 15:17:07 -0500326 : fTextureSampler(texture, GrSamplerParams::ClampNoFilter())
Robert Phillipse98234f2017-01-09 14:23:59 -0500327 , fTextureDomain(texture, GrTextureDomain::MakeTexelDomain(subset),
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400328 GrTextureDomain::kDecal_Mode) {
Brian Salomon0bbecb22016-11-17 11:38:22 -0500329 this->addTextureSampler(&fTextureSampler);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400330 fDeviceSpaceOffset.fX = deviceSpaceOffset.fX - subset.fLeft;
331 fDeviceSpaceOffset.fY = deviceSpaceOffset.fY - subset.fTop;
332 this->initClassID<GrDeviceSpaceTextureDecalFragmentProcessor>();
333 this->setWillReadFragmentPosition();
334}
335
336GrGLSLFragmentProcessor* GrDeviceSpaceTextureDecalFragmentProcessor::onCreateGLSLInstance() const {
337 class GLSLProcessor : public GrGLSLFragmentProcessor {
338 public:
339 void emitCode(EmitArgs& args) override {
340 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
341 args.fFp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
342 const char* scaleAndTranslateName;
343 fScaleAndTranslateUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
344 kVec4f_GrSLType,
345 kDefault_GrSLPrecision,
346 "scaleAndTranslate",
347 &scaleAndTranslateName);
348 args.fFragBuilder->codeAppendf("vec2 coords = %s.xy * %s.xy + %s.zw;",
349 args.fFragBuilder->fragmentPosition(),
350 scaleAndTranslateName, scaleAndTranslateName);
351 fGLDomain.sampleTexture(args.fFragBuilder,
352 args.fUniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500353 args.fShaderCaps,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400354 dstdfp.fTextureDomain,
355 args.fOutputColor,
356 SkString("coords"),
357 args.fTexSamplers[0],
358 args.fInputColor);
359 }
360
361 protected:
362 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& fp) override {
363 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
364 fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
Brian Salomondb4183d2016-11-17 12:48:40 -0500365 GrTexture* texture = dstdfp.textureSampler(0).texture();
Robert Phillipse98234f2017-01-09 14:23:59 -0500366 fGLDomain.setData(pdman, dstdfp.fTextureDomain, texture);
Brian Salomon0bbecb22016-11-17 11:38:22 -0500367 float iw = 1.f / texture->width();
368 float ih = 1.f / texture->height();
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400369 float scaleAndTransData[4] = {
370 iw, ih,
371 -dstdfp.fDeviceSpaceOffset.fX * iw, -dstdfp.fDeviceSpaceOffset.fY * ih
372 };
Brian Salomon0bbecb22016-11-17 11:38:22 -0500373 if (texture->origin() == kBottomLeft_GrSurfaceOrigin) {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400374 scaleAndTransData[1] = -scaleAndTransData[1];
375 scaleAndTransData[3] = 1 - scaleAndTransData[3];
376 }
377 pdman.set4fv(fScaleAndTranslateUni, 1, scaleAndTransData);
378 }
379
380 private:
381 GrTextureDomain::GLDomain fGLDomain;
382 UniformHandle fScaleAndTranslateUni;
383 };
384
385 return new GLSLProcessor;
386}
387
388bool GrDeviceSpaceTextureDecalFragmentProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
389 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
390 fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
Brian Salomondb4183d2016-11-17 12:48:40 -0500391 return dstdfp.fTextureSampler.texture() == fTextureSampler.texture() &&
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400392 dstdfp.fDeviceSpaceOffset == fDeviceSpaceOffset &&
393 dstdfp.fTextureDomain == fTextureDomain;
394}
395
396void GrDeviceSpaceTextureDecalFragmentProcessor::onComputeInvariantOutput(
397 GrInvariantOutput* inout) const {
Brian Salomondb4183d2016-11-17 12:48:40 -0500398 if (GrPixelConfigIsAlphaOnly(this->textureSampler(0).texture()->config())) {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400399 inout->mulByUnknownSingleComponent();
400 } else {
401 inout->mulByUnknownFourComponents();
402 }
403}
404
405///////////////////////////////////////////////////////////////////////////////
406
407GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDeviceSpaceTextureDecalFragmentProcessor);
408
409sk_sp<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::TestCreate(
410 GrProcessorTestData* d) {
411 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
412 : GrProcessorUnitTest::kAlphaTextureIdx;
413 SkIRect subset;
414 subset.fLeft = d->fRandom->nextULessThan(d->fTextures[texIdx]->width() - 1);
415 subset.fRight = d->fRandom->nextRangeU(subset.fLeft, d->fTextures[texIdx]->width());
416 subset.fTop = d->fRandom->nextULessThan(d->fTextures[texIdx]->height() - 1);
417 subset.fBottom = d->fRandom->nextRangeU(subset.fTop, d->fTextures[texIdx]->height());
418 SkIPoint pt;
419 pt.fX = d->fRandom->nextULessThan(2048);
420 pt.fY = d->fRandom->nextULessThan(2048);
421 return GrDeviceSpaceTextureDecalFragmentProcessor::Make(d->fTextures[texIdx], subset, pt);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000422}