blob: 81e8da1a7de3d071c2e4f65cecd00845426de2c0 [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
Robert Phillips1afd4cd2018-01-08 13:40:32 -050010#include "GrProxyProvider.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"
Robert Phillips646e4292017-06-13 12:44:56 -040014#include "GrTexture.h"
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000015#include "SkFloatingPoint.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 Phillipsb66b42f2017-03-14 08:53:02 -040022static bool can_ignore_rect(GrTextureProxy* proxy, const SkRect& domain) {
Robert Phillips1afd4cd2018-01-08 13:40:32 -050023 if (GrProxyProvider::IsFunctionallyExact(proxy)) {
Robert Phillips40fd7c92017-01-30 08:06:27 -050024 const SkIRect kFullRect = SkIRect::MakeWH(proxy->width(), proxy->height());
25
26 return domain.contains(kFullRect);
27 }
28
29 return false;
30}
31
Robert Phillips40fd7c92017-01-30 08:06:27 -050032GrTextureDomain::GrTextureDomain(GrTextureProxy* proxy, const SkRect& domain, Mode mode, int index)
33 : fMode(mode)
34 , fIndex(index) {
35
36 if (kIgnore_Mode == fMode) {
37 return;
38 }
39
40 if (kClamp_Mode == mode && can_ignore_rect(proxy, domain)) {
41 fMode = kIgnore_Mode;
42 return;
43 }
44
45 const SkRect kFullRect = SkRect::MakeIWH(proxy->width(), proxy->height());
46
47 // We don't currently handle domains that are empty or don't intersect the texture.
48 // It is OK if the domain rect is a line or point, but it should not be inverted. We do not
49 // handle rects that do not intersect the [0..1]x[0..1] rect.
50 SkASSERT(domain.fLeft <= domain.fRight);
51 SkASSERT(domain.fTop <= domain.fBottom);
52 fDomain.fLeft = SkScalarPin(domain.fLeft, 0.0f, kFullRect.fRight);
53 fDomain.fRight = SkScalarPin(domain.fRight, fDomain.fLeft, kFullRect.fRight);
54 fDomain.fTop = SkScalarPin(domain.fTop, 0.0f, kFullRect.fBottom);
55 fDomain.fBottom = SkScalarPin(domain.fBottom, fDomain.fTop, kFullRect.fBottom);
56 SkASSERT(fDomain.fLeft <= fDomain.fRight);
57 SkASSERT(fDomain.fTop <= fDomain.fBottom);
58}
59
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000060//////////////////////////////////////////////////////////////////////////////
61
egdaniel2d721d32015-11-11 13:06:05 -080062void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
egdaniel7ea439b2015-12-03 09:20:44 -080063 GrGLSLUniformHandler* uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -050064 const GrShaderCaps* shaderCaps,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000065 const GrTextureDomain& textureDomain,
66 const char* outColor,
67 const SkString& inCoords,
egdaniel09aa1fc2016-04-20 07:09:46 -070068 GrGLSLFragmentProcessor::SamplerHandle sampler,
Brian Osman2240be92017-10-18 13:15:13 -040069 const char* inModulateColor) {
Hans Wennborgc63ec5c2017-12-08 18:56:23 -080070 SkASSERT(!fHasMode || textureDomain.mode() == fMode);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000071 SkDEBUGCODE(fMode = textureDomain.mode();)
Hans Wennborgc63ec5c2017-12-08 18:56:23 -080072 SkDEBUGCODE(fHasMode = true;)
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000073
joshualitt5ae5fc52014-07-29 12:59:27 -070074 if (textureDomain.mode() != kIgnore_Mode && !fDomainUni.isValid()) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000075 const char* name;
76 SkString uniName("TexDom");
77 if (textureDomain.fIndex >= 0) {
78 uniName.appendS32(textureDomain.fIndex);
79 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -040080 fDomainUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
egdaniel7ea439b2015-12-03 09:20:44 -080081 uniName.c_str(), &name);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000082 fDomainName = name;
83 }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000084
joshualitt5ae5fc52014-07-29 12:59:27 -070085 switch (textureDomain.mode()) {
86 case kIgnore_Mode: {
jvanverth3fc65602015-07-22 08:41:51 -070087 builder->codeAppendf("%s = ", outColor);
Brian Osmanc4689632016-12-19 17:04:59 -050088 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
Brian Osman2240be92017-10-18 13:15:13 -040089 kFloat2_GrSLType);
jvanverth3fc65602015-07-22 08:41:51 -070090 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -070091 break;
92 }
93 case kClamp_Mode: {
94 SkString clampedCoords;
jvanverth3fc65602015-07-22 08:41:51 -070095 clampedCoords.appendf("clamp(%s, %s.xy, %s.zw)",
joshualitt5ae5fc52014-07-29 12:59:27 -070096 inCoords.c_str(), fDomainName.c_str(), fDomainName.c_str());
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000097
jvanverth3fc65602015-07-22 08:41:51 -070098 builder->codeAppendf("%s = ", outColor);
Brian Osmanc4689632016-12-19 17:04:59 -050099 builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
Brian Osman2240be92017-10-18 13:15:13 -0400100 kFloat2_GrSLType);
jvanverth3fc65602015-07-22 08:41:51 -0700101 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700102 break;
103 }
104 case kDecal_Mode: {
105 // Add a block since we're going to declare variables.
egdaniel2d721d32015-11-11 13:06:05 -0800106 GrGLSLShaderBuilder::ShaderBlock block(builder);
joshualitt5ae5fc52014-07-29 12:59:27 -0700107
108 const char* domain = fDomainName.c_str();
Brian Salomon1edc5b92016-11-29 13:43:46 -0500109 if (!shaderCaps->canUseAnyFunctionInShader()) {
joshualitt5ae5fc52014-07-29 12:59:27 -0700110 // On the NexusS and GalaxyNexus, the other path (with the 'any'
111 // call) causes the compilation error "Calls to any function that
112 // may require a gradient calculation inside a conditional block
113 // may return undefined results". This appears to be an issue with
114 // the 'any' call since even the simple "result=black; if (any())
115 // result=white;" code fails to compile.
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400116 builder->codeAppend("half4 outside = half4(0.0, 0.0, 0.0, 0.0);");
117 builder->codeAppend("half4 inside = ");
Brian Osmanc4689632016-12-19 17:04:59 -0500118 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
Brian Osman2240be92017-10-18 13:15:13 -0400119 kFloat2_GrSLType);
jvanverth3fc65602015-07-22 08:41:51 -0700120 builder->codeAppend(";");
halcanary9d524f22016-03-29 09:03:52 -0700121
Ethan Nicholas8aa45692017-09-20 11:24:15 -0400122 builder->codeAppendf("float x = (%s).x;", inCoords.c_str());
123 builder->codeAppendf("float y = (%s).y;", inCoords.c_str());
joshualitt5ae5fc52014-07-29 12:59:27 -0700124
jvanverth3fc65602015-07-22 08:41:51 -0700125 builder->codeAppendf("x = abs(2.0*(x - %s.x)/(%s.z - %s.x) - 1.0);",
126 domain, domain, domain);
127 builder->codeAppendf("y = abs(2.0*(y - %s.y)/(%s.w - %s.y) - 1.0);",
128 domain, domain, domain);
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400129 builder->codeAppend("half blend = step(1.0, max(x, y));");
jvanverth3fc65602015-07-22 08:41:51 -0700130 builder->codeAppendf("%s = mix(inside, outside, blend);", outColor);
joshualitt5ae5fc52014-07-29 12:59:27 -0700131 } else {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400132 builder->codeAppend("bool4 outside;\n");
jvanverth3fc65602015-07-22 08:41:51 -0700133 builder->codeAppendf("outside.xy = lessThan(%s, %s.xy);", inCoords.c_str(),
joshualitt5ae5fc52014-07-29 12:59:27 -0700134 domain);
jvanverth3fc65602015-07-22 08:41:51 -0700135 builder->codeAppendf("outside.zw = greaterThan(%s, %s.zw);", inCoords.c_str(),
joshualitt5ae5fc52014-07-29 12:59:27 -0700136 domain);
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400137 builder->codeAppendf("%s = any(outside) ? half4(0.0, 0.0, 0.0, 0.0) : ",
joshualitt5ae5fc52014-07-29 12:59:27 -0700138 outColor);
Brian Osmanc4689632016-12-19 17:04:59 -0500139 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
Brian Osman2240be92017-10-18 13:15:13 -0400140 kFloat2_GrSLType);
jvanverth3fc65602015-07-22 08:41:51 -0700141 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700142 }
143 break;
144 }
145 case kRepeat_Mode: {
146 SkString clampedCoords;
jvanverth3fc65602015-07-22 08:41:51 -0700147 clampedCoords.printf("mod(%s - %s.xy, %s.zw - %s.xy) + %s.xy",
joshualitt5ae5fc52014-07-29 12:59:27 -0700148 inCoords.c_str(), fDomainName.c_str(), fDomainName.c_str(),
149 fDomainName.c_str(), fDomainName.c_str());
150
jvanverth3fc65602015-07-22 08:41:51 -0700151 builder->codeAppendf("%s = ", outColor);
Brian Osmanc4689632016-12-19 17:04:59 -0500152 builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
Brian Osman2240be92017-10-18 13:15:13 -0400153 kFloat2_GrSLType);
jvanverth3fc65602015-07-22 08:41:51 -0700154 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700155 break;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000156 }
157 }
158}
159
egdaniel018fb622015-10-28 07:26:40 -0700160void GrTextureDomain::GLDomain::setData(const GrGLSLProgramDataManager& pdman,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000161 const GrTextureDomain& textureDomain,
Robert Phillipsc686ce32017-07-21 14:12:29 -0400162 GrSurfaceProxy* proxy) {
163 GrTexture* tex = proxy->priv().peekTexture();
Hans Wennborgc63ec5c2017-12-08 18:56:23 -0800164 SkASSERT(fHasMode && textureDomain.mode() == fMode);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000165 if (kIgnore_Mode != textureDomain.mode()) {
Robert Phillipse98234f2017-01-09 14:23:59 -0500166 SkScalar wInv = SK_Scalar1 / tex->width();
167 SkScalar hInv = SK_Scalar1 / tex->height();
168
egdaniel018fb622015-10-28 07:26:40 -0700169 float values[kPrevDomainCount] = {
Robert Phillipse98234f2017-01-09 14:23:59 -0500170 SkScalarToFloat(textureDomain.domain().fLeft * wInv),
171 SkScalarToFloat(textureDomain.domain().fTop * hInv),
172 SkScalarToFloat(textureDomain.domain().fRight * wInv),
173 SkScalarToFloat(textureDomain.domain().fBottom * hInv)
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000174 };
Robert Phillipse98234f2017-01-09 14:23:59 -0500175
176 SkASSERT(values[0] >= 0.0f && values[0] <= 1.0f);
177 SkASSERT(values[1] >= 0.0f && values[1] <= 1.0f);
178 SkASSERT(values[2] >= 0.0f && values[2] <= 1.0f);
179 SkASSERT(values[3] >= 0.0f && values[3] <= 1.0f);
180
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000181 // vertical flip if necessary
Robert Phillipsc686ce32017-07-21 14:12:29 -0400182 if (kBottomLeft_GrSurfaceOrigin == proxy->origin()) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000183 values[1] = 1.0f - values[1];
184 values[3] = 1.0f - values[3];
185 // The top and bottom were just flipped, so correct the ordering
186 // of elements so that values = (l, t, r, b).
187 SkTSwap(values[1], values[3]);
188 }
egdaniel018fb622015-10-28 07:26:40 -0700189 if (0 != memcmp(values, fPrevDomain, kPrevDomainCount * sizeof(float))) {
kkinnunen7510b222014-07-30 00:04:16 -0700190 pdman.set4fv(fDomainUni, 1, values);
egdaniel018fb622015-10-28 07:26:40 -0700191 memcpy(fPrevDomain, values, kPrevDomainCount * sizeof(float));
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000192 }
193 }
194}
195
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000196///////////////////////////////////////////////////////////////////////////////
Brian Salomon587e08f2017-01-27 10:59:27 -0500197inline GrFragmentProcessor::OptimizationFlags GrTextureDomainEffect::OptFlags(
Robert Phillips40fd7c92017-01-30 08:06:27 -0500198 GrPixelConfig config, GrTextureDomain::Mode mode) {
199 if (mode == GrTextureDomain::kDecal_Mode || !GrPixelConfigIsOpaque(config)) {
Brian Salomonf3b995b2017-02-15 10:22:23 -0500200 return GrFragmentProcessor::kCompatibleWithCoverageAsAlpha_OptimizationFlag;
Brian Salomon587e08f2017-01-27 10:59:27 -0500201 } else {
Brian Salomonf3b995b2017-02-15 10:22:23 -0500202 return GrFragmentProcessor::kCompatibleWithCoverageAsAlpha_OptimizationFlag |
Brian Salomon587e08f2017-01-27 10:59:27 -0500203 GrFragmentProcessor::kPreservesOpaqueInput_OptimizationFlag;
204 }
205}
206
Brian Salomonaff329b2017-08-11 09:40:37 -0400207std::unique_ptr<GrFragmentProcessor> GrTextureDomainEffect::Make(
208 sk_sp<GrTextureProxy> proxy,
Brian Salomonaff329b2017-08-11 09:40:37 -0400209 const SkMatrix& matrix,
210 const SkRect& domain,
211 GrTextureDomain::Mode mode,
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400212 GrSamplerState::Filter filterMode) {
Robert Phillips40fd7c92017-01-30 08:06:27 -0500213 if (GrTextureDomain::kIgnore_Mode == mode ||
214 (GrTextureDomain::kClamp_Mode == mode && can_ignore_rect(proxy.get(), domain))) {
Brian Osman2240be92017-10-18 13:15:13 -0400215 return GrSimpleTextureEffect::Make(std::move(proxy), matrix, filterMode);
Robert Phillips40fd7c92017-01-30 08:06:27 -0500216 } else {
Brian Salomonaff329b2017-08-11 09:40:37 -0400217 return std::unique_ptr<GrFragmentProcessor>(new GrTextureDomainEffect(
Brian Osman2240be92017-10-18 13:15:13 -0400218 std::move(proxy), matrix, domain, mode, filterMode));
Robert Phillips40fd7c92017-01-30 08:06:27 -0500219 }
220}
221
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400222GrTextureDomainEffect::GrTextureDomainEffect(sk_sp<GrTextureProxy> proxy,
Robert Phillips40fd7c92017-01-30 08:06:27 -0500223 const SkMatrix& matrix,
224 const SkRect& domain,
225 GrTextureDomain::Mode mode,
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400226 GrSamplerState::Filter filterMode)
Ethan Nicholasabff9562017-10-09 10:54:08 -0400227 : INHERITED(kGrTextureDomainEffect_ClassID, OptFlags(proxy->config(), mode))
Brian Salomon6cd51b52017-07-26 19:07:15 -0400228 , fCoordTransform(matrix, proxy.get())
229 , fTextureDomain(proxy.get(), domain, mode)
Brian Osman2240be92017-10-18 13:15:13 -0400230 , fTextureSampler(std::move(proxy), filterMode) {
Robert Phillips40fd7c92017-01-30 08:06:27 -0500231 SkASSERT(mode != GrTextureDomain::kRepeat_Mode ||
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400232 filterMode == GrSamplerState::Filter::kNearest);
Brian Salomon6cd51b52017-07-26 19:07:15 -0400233 this->addCoordTransform(&fCoordTransform);
234 this->addTextureSampler(&fTextureSampler);
Robert Phillips40fd7c92017-01-30 08:06:27 -0500235}
236
Brian Salomon3f6f9652017-07-28 07:34:05 -0400237GrTextureDomainEffect::GrTextureDomainEffect(const GrTextureDomainEffect& that)
Ethan Nicholasabff9562017-10-09 10:54:08 -0400238 : INHERITED(kGrTextureDomainEffect_ClassID, that.optimizationFlags())
Brian Salomon3f6f9652017-07-28 07:34:05 -0400239 , fCoordTransform(that.fCoordTransform)
240 , fTextureDomain(that.fTextureDomain)
Brian Osman2240be92017-10-18 13:15:13 -0400241 , fTextureSampler(that.fTextureSampler) {
Brian Salomon3f6f9652017-07-28 07:34:05 -0400242 this->addCoordTransform(&fCoordTransform);
243 this->addTextureSampler(&fTextureSampler);
244}
245
Brian Salomon94efbf52016-11-29 13:43:05 -0500246void GrTextureDomainEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800247 GrProcessorKeyBuilder* b) const {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400248 b->add32(GrTextureDomain::GLDomain::DomainKey(fTextureDomain));
joshualitteb2a6762014-12-04 11:35:33 -0800249}
250
egdaniel57d3b032015-11-13 11:57:27 -0800251GrGLSLFragmentProcessor* GrTextureDomainEffect::onCreateGLSLInstance() const {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400252 class GLSLProcessor : public GrGLSLFragmentProcessor {
253 public:
254 void emitCode(EmitArgs& args) override {
255 const GrTextureDomainEffect& tde = args.fFp.cast<GrTextureDomainEffect>();
256 const GrTextureDomain& domain = tde.fTextureDomain;
257
258 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
259 SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
Brian Osmanc4689632016-12-19 17:04:59 -0500260
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400261 fGLDomain.sampleTexture(fragBuilder,
262 args.fUniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500263 args.fShaderCaps,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400264 domain,
265 args.fOutputColor,
266 coords2D,
267 args.fTexSamplers[0],
Brian Osman2240be92017-10-18 13:15:13 -0400268 args.fInputColor);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400269 }
270
271 protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400272 void onSetData(const GrGLSLProgramDataManager& pdman,
273 const GrFragmentProcessor& fp) override {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400274 const GrTextureDomainEffect& tde = fp.cast<GrTextureDomainEffect>();
275 const GrTextureDomain& domain = tde.fTextureDomain;
Robert Phillipsc686ce32017-07-21 14:12:29 -0400276 GrSurfaceProxy* proxy = tde.textureSampler(0).proxy();
Robert Phillips9bee2e52017-05-29 12:37:20 -0400277
Robert Phillipsc686ce32017-07-21 14:12:29 -0400278 fGLDomain.setData(pdman, domain, proxy);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400279 }
280
281 private:
282 GrTextureDomain::GLDomain fGLDomain;
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400283 };
284
285 return new GLSLProcessor;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000286}
287
bsalomon0e08fc12014-10-15 08:19:04 -0700288bool GrTextureDomainEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
joshualitt49586be2014-09-16 08:21:41 -0700289 const GrTextureDomainEffect& s = sBase.cast<GrTextureDomainEffect>();
Brian Salomona7c4c292016-11-17 12:47:06 -0500290 return this->fTextureDomain == s.fTextureDomain;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000291}
292
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000293///////////////////////////////////////////////////////////////////////////////
294
joshualittb0a8a372014-09-23 09:50:21 -0700295GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrTextureDomainEffect);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000296
Hal Canary6f6961e2017-01-31 13:50:44 -0500297#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -0400298std::unique_ptr<GrFragmentProcessor> GrTextureDomainEffect::TestCreate(GrProcessorTestData* d) {
Robert Phillips40fd7c92017-01-30 08:06:27 -0500299 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
300 : GrProcessorUnitTest::kAlphaTextureIdx;
301 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000302 SkRect domain;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500303 domain.fLeft = d->fRandom->nextRangeScalar(0, proxy->width());
304 domain.fRight = d->fRandom->nextRangeScalar(domain.fLeft, proxy->width());
305 domain.fTop = d->fRandom->nextRangeScalar(0, proxy->height());
306 domain.fBottom = d->fRandom->nextRangeScalar(domain.fTop, proxy->height());
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000307 GrTextureDomain::Mode mode =
joshualitt0067ff52015-07-08 14:26:19 -0700308 (GrTextureDomain::Mode) d->fRandom->nextULessThan(GrTextureDomain::kModeCount);
309 const SkMatrix& matrix = GrTest::TestMatrix(d->fRandom);
310 bool bilerp = mode != GrTextureDomain::kRepeat_Mode ? d->fRandom->nextBool() : false;
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400311 return GrTextureDomainEffect::Make(
312 std::move(proxy),
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400313 matrix,
314 domain,
315 mode,
316 bilerp ? GrSamplerState::Filter::kBilerp : GrSamplerState::Filter::kNearest);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400317}
Hal Canary6f6961e2017-01-31 13:50:44 -0500318#endif
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400319
320///////////////////////////////////////////////////////////////////////////////
Brian Salomonaff329b2017-08-11 09:40:37 -0400321std::unique_ptr<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::Make(
322 sk_sp<GrTextureProxy> proxy, const SkIRect& subset, const SkIPoint& deviceSpaceOffset) {
323 return std::unique_ptr<GrFragmentProcessor>(new GrDeviceSpaceTextureDecalFragmentProcessor(
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400324 std::move(proxy), subset, deviceSpaceOffset));
Robert Phillips40fd7c92017-01-30 08:06:27 -0500325}
326
327GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400328 sk_sp<GrTextureProxy> proxy, const SkIRect& subset, const SkIPoint& deviceSpaceOffset)
Ethan Nicholasabff9562017-10-09 10:54:08 -0400329 : INHERITED(kGrDeviceSpaceTextureDecalFragmentProcessor_ClassID,
330 kCompatibleWithCoverageAsAlpha_OptimizationFlag)
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400331 , fTextureSampler(proxy, GrSamplerState::ClampNearest())
Robert Phillips40fd7c92017-01-30 08:06:27 -0500332 , fTextureDomain(proxy.get(), GrTextureDomain::MakeTexelDomain(subset),
333 GrTextureDomain::kDecal_Mode) {
334 this->addTextureSampler(&fTextureSampler);
335 fDeviceSpaceOffset.fX = deviceSpaceOffset.fX - subset.fLeft;
336 fDeviceSpaceOffset.fY = deviceSpaceOffset.fY - subset.fTop;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500337}
338
Brian Salomon1a2a7ab2017-07-26 13:11:51 -0400339GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
340 const GrDeviceSpaceTextureDecalFragmentProcessor& that)
Ethan Nicholasabff9562017-10-09 10:54:08 -0400341 : INHERITED(kGrDeviceSpaceTextureDecalFragmentProcessor_ClassID,
342 kCompatibleWithCoverageAsAlpha_OptimizationFlag)
Brian Salomon1a2a7ab2017-07-26 13:11:51 -0400343 , fTextureSampler(that.fTextureSampler)
344 , fTextureDomain(that.fTextureDomain)
345 , fDeviceSpaceOffset(that.fDeviceSpaceOffset) {
Brian Salomon1a2a7ab2017-07-26 13:11:51 -0400346 this->addTextureSampler(&fTextureSampler);
347}
348
Brian Salomonaff329b2017-08-11 09:40:37 -0400349std::unique_ptr<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::clone() const {
350 return std::unique_ptr<GrFragmentProcessor>(
351 new GrDeviceSpaceTextureDecalFragmentProcessor(*this));
Brian Salomon1a2a7ab2017-07-26 13:11:51 -0400352}
353
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400354GrGLSLFragmentProcessor* GrDeviceSpaceTextureDecalFragmentProcessor::onCreateGLSLInstance() const {
355 class GLSLProcessor : public GrGLSLFragmentProcessor {
356 public:
357 void emitCode(EmitArgs& args) override {
358 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
359 args.fFp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
360 const char* scaleAndTranslateName;
361 fScaleAndTranslateUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400362 kHalf4_GrSLType,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400363 "scaleAndTranslate",
364 &scaleAndTranslateName);
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400365 args.fFragBuilder->codeAppendf("half2 coords = sk_FragCoord.xy * %s.xy + %s.zw;",
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400366 scaleAndTranslateName, scaleAndTranslateName);
367 fGLDomain.sampleTexture(args.fFragBuilder,
368 args.fUniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500369 args.fShaderCaps,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400370 dstdfp.fTextureDomain,
371 args.fOutputColor,
372 SkString("coords"),
373 args.fTexSamplers[0],
374 args.fInputColor);
375 }
376
377 protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400378 void onSetData(const GrGLSLProgramDataManager& pdman,
379 const GrFragmentProcessor& fp) override {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400380 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
381 fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
Robert Phillipsc686ce32017-07-21 14:12:29 -0400382 GrSurfaceProxy* proxy = dstdfp.textureSampler(0).proxy();
383 GrTexture* texture = proxy->priv().peekTexture();
Robert Phillips9bee2e52017-05-29 12:37:20 -0400384
Robert Phillipsc686ce32017-07-21 14:12:29 -0400385 fGLDomain.setData(pdman, dstdfp.fTextureDomain, proxy);
Brian Salomon0bbecb22016-11-17 11:38:22 -0500386 float iw = 1.f / texture->width();
387 float ih = 1.f / texture->height();
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400388 float scaleAndTransData[4] = {
389 iw, ih,
390 -dstdfp.fDeviceSpaceOffset.fX * iw, -dstdfp.fDeviceSpaceOffset.fY * ih
391 };
Robert Phillipsc686ce32017-07-21 14:12:29 -0400392 if (proxy->origin() == kBottomLeft_GrSurfaceOrigin) {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400393 scaleAndTransData[1] = -scaleAndTransData[1];
394 scaleAndTransData[3] = 1 - scaleAndTransData[3];
395 }
396 pdman.set4fv(fScaleAndTranslateUni, 1, scaleAndTransData);
397 }
398
399 private:
400 GrTextureDomain::GLDomain fGLDomain;
401 UniformHandle fScaleAndTranslateUni;
402 };
403
404 return new GLSLProcessor;
405}
406
407bool GrDeviceSpaceTextureDecalFragmentProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
408 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
409 fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
Brian Salomon1a2a7ab2017-07-26 13:11:51 -0400410 return dstdfp.fTextureSampler.proxy()->underlyingUniqueID() ==
411 fTextureSampler.proxy()->underlyingUniqueID() &&
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400412 dstdfp.fDeviceSpaceOffset == fDeviceSpaceOffset &&
413 dstdfp.fTextureDomain == fTextureDomain;
414}
415
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400416///////////////////////////////////////////////////////////////////////////////
417
418GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDeviceSpaceTextureDecalFragmentProcessor);
419
Hal Canary6f6961e2017-01-31 13:50:44 -0500420#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -0400421std::unique_ptr<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::TestCreate(
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400422 GrProcessorTestData* d) {
423 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
424 : GrProcessorUnitTest::kAlphaTextureIdx;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500425 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400426 SkIRect subset;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500427 subset.fLeft = d->fRandom->nextULessThan(proxy->width() - 1);
428 subset.fRight = d->fRandom->nextRangeU(subset.fLeft, proxy->width());
429 subset.fTop = d->fRandom->nextULessThan(proxy->height() - 1);
430 subset.fBottom = d->fRandom->nextRangeU(subset.fTop, proxy->height());
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400431 SkIPoint pt;
432 pt.fX = d->fRandom->nextULessThan(2048);
433 pt.fY = d->fRandom->nextULessThan(2048);
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400434 return GrDeviceSpaceTextureDecalFragmentProcessor::Make(std::move(proxy), subset, pt);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000435}
Hal Canary6f6961e2017-01-31 13:50:44 -0500436#endif