blob: 5101762bd949b32c5a9b0bcdb16b0576f07424f5 [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 Phillipsb66b42f2017-03-14 08:53:02 -040010#include "GrResourceProvider.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"
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 Phillipsb66b42f2017-03-14 08:53:02 -040023static bool can_ignore_rect(GrTextureProxy* proxy, const SkRect& domain) {
24 if (GrResourceProvider::IsFunctionallyExact(proxy)) {
Robert Phillips40fd7c92017-01-30 08:06:27 -050025 const SkIRect kFullRect = SkIRect::MakeWH(proxy->width(), proxy->height());
26
27 return domain.contains(kFullRect);
28 }
29
30 return false;
31}
32
Robert Phillips40fd7c92017-01-30 08:06:27 -050033GrTextureDomain::GrTextureDomain(GrTextureProxy* proxy, const SkRect& domain, Mode mode, int index)
34 : fMode(mode)
35 , fIndex(index) {
36
37 if (kIgnore_Mode == fMode) {
38 return;
39 }
40
41 if (kClamp_Mode == mode && can_ignore_rect(proxy, domain)) {
42 fMode = kIgnore_Mode;
43 return;
44 }
45
46 const SkRect kFullRect = SkRect::MakeIWH(proxy->width(), proxy->height());
47
48 // We don't currently handle domains that are empty or don't intersect the texture.
49 // It is OK if the domain rect is a line or point, but it should not be inverted. We do not
50 // handle rects that do not intersect the [0..1]x[0..1] rect.
51 SkASSERT(domain.fLeft <= domain.fRight);
52 SkASSERT(domain.fTop <= domain.fBottom);
53 fDomain.fLeft = SkScalarPin(domain.fLeft, 0.0f, kFullRect.fRight);
54 fDomain.fRight = SkScalarPin(domain.fRight, fDomain.fLeft, kFullRect.fRight);
55 fDomain.fTop = SkScalarPin(domain.fTop, 0.0f, kFullRect.fBottom);
56 fDomain.fBottom = SkScalarPin(domain.fBottom, fDomain.fTop, kFullRect.fBottom);
57 SkASSERT(fDomain.fLeft <= fDomain.fRight);
58 SkASSERT(fDomain.fTop <= fDomain.fBottom);
59}
60
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000061//////////////////////////////////////////////////////////////////////////////
62
egdaniel2d721d32015-11-11 13:06:05 -080063void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
egdaniel7ea439b2015-12-03 09:20:44 -080064 GrGLSLUniformHandler* uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -050065 const GrShaderCaps* shaderCaps,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000066 const GrTextureDomain& textureDomain,
67 const char* outColor,
68 const SkString& inCoords,
egdaniel09aa1fc2016-04-20 07:09:46 -070069 GrGLSLFragmentProcessor::SamplerHandle sampler,
Brian Osmanc4689632016-12-19 17:04:59 -050070 const char* inModulateColor,
71 GrGLSLColorSpaceXformHelper* colorXformHelper) {
reed@google.comd7b1af62013-12-09 20:31:50 +000072 SkASSERT((Mode)-1 == fMode || textureDomain.mode() == fMode);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000073 SkDEBUGCODE(fMode = textureDomain.mode();)
74
joshualitt5ae5fc52014-07-29 12:59:27 -070075 if (textureDomain.mode() != kIgnore_Mode && !fDomainUni.isValid()) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000076 const char* name;
77 SkString uniName("TexDom");
78 if (textureDomain.fIndex >= 0) {
79 uniName.appendS32(textureDomain.fIndex);
80 }
Brian Salomon1d816b92017-08-17 11:07:59 -040081 fDomainUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
82 kVec4f_GrSLType, kDefault_GrSLPrecision,
egdaniel7ea439b2015-12-03 09:20:44 -080083 uniName.c_str(), &name);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000084 fDomainName = name;
85 }
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000086
joshualitt5ae5fc52014-07-29 12:59:27 -070087 switch (textureDomain.mode()) {
88 case kIgnore_Mode: {
jvanverth3fc65602015-07-22 08:41:51 -070089 builder->codeAppendf("%s = ", outColor);
Brian Osmanc4689632016-12-19 17:04:59 -050090 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
Brian Salomon1d816b92017-08-17 11:07:59 -040091 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -070092 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -070093 break;
94 }
95 case kClamp_Mode: {
96 SkString clampedCoords;
jvanverth3fc65602015-07-22 08:41:51 -070097 clampedCoords.appendf("clamp(%s, %s.xy, %s.zw)",
joshualitt5ae5fc52014-07-29 12:59:27 -070098 inCoords.c_str(), fDomainName.c_str(), fDomainName.c_str());
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +000099
jvanverth3fc65602015-07-22 08:41:51 -0700100 builder->codeAppendf("%s = ", outColor);
Brian Osmanc4689632016-12-19 17:04:59 -0500101 builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
Brian Salomon1d816b92017-08-17 11:07:59 -0400102 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700103 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700104 break;
105 }
106 case kDecal_Mode: {
107 // Add a block since we're going to declare variables.
egdaniel2d721d32015-11-11 13:06:05 -0800108 GrGLSLShaderBuilder::ShaderBlock block(builder);
joshualitt5ae5fc52014-07-29 12:59:27 -0700109
110 const char* domain = fDomainName.c_str();
Brian Salomon1edc5b92016-11-29 13:43:46 -0500111 if (!shaderCaps->canUseAnyFunctionInShader()) {
joshualitt5ae5fc52014-07-29 12:59:27 -0700112 // On the NexusS and GalaxyNexus, the other path (with the 'any'
113 // call) causes the compilation error "Calls to any function that
114 // may require a gradient calculation inside a conditional block
115 // may return undefined results". This appears to be an issue with
116 // the 'any' call since even the simple "result=black; if (any())
117 // result=white;" code fails to compile.
Brian Salomon1d816b92017-08-17 11:07:59 -0400118 builder->codeAppend("float4 outside = float4(0.0, 0.0, 0.0, 0.0);");
119 builder->codeAppend("float4 inside = ");
Brian Osmanc4689632016-12-19 17:04:59 -0500120 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
Brian Salomon1d816b92017-08-17 11:07:59 -0400121 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700122 builder->codeAppend(";");
halcanary9d524f22016-03-29 09:03:52 -0700123
Brian Salomon1d816b92017-08-17 11:07:59 -0400124 builder->codeAppendf("highp float x = (%s).x;", inCoords.c_str());
125 builder->codeAppendf("highp float y = (%s).y;", inCoords.c_str());
joshualitt5ae5fc52014-07-29 12:59:27 -0700126
jvanverth3fc65602015-07-22 08:41:51 -0700127 builder->codeAppendf("x = abs(2.0*(x - %s.x)/(%s.z - %s.x) - 1.0);",
128 domain, domain, domain);
129 builder->codeAppendf("y = abs(2.0*(y - %s.y)/(%s.w - %s.y) - 1.0);",
130 domain, domain, domain);
Brian Salomon1d816b92017-08-17 11:07:59 -0400131 builder->codeAppend("float blend = step(1.0, max(x, y));");
jvanverth3fc65602015-07-22 08:41:51 -0700132 builder->codeAppendf("%s = mix(inside, outside, blend);", outColor);
joshualitt5ae5fc52014-07-29 12:59:27 -0700133 } else {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400134 builder->codeAppend("bool4 outside;\n");
jvanverth3fc65602015-07-22 08:41:51 -0700135 builder->codeAppendf("outside.xy = lessThan(%s, %s.xy);", inCoords.c_str(),
joshualitt5ae5fc52014-07-29 12:59:27 -0700136 domain);
jvanverth3fc65602015-07-22 08:41:51 -0700137 builder->codeAppendf("outside.zw = greaterThan(%s, %s.zw);", inCoords.c_str(),
joshualitt5ae5fc52014-07-29 12:59:27 -0700138 domain);
Brian Salomon1d816b92017-08-17 11:07:59 -0400139 builder->codeAppendf("%s = any(outside) ? float4(0.0, 0.0, 0.0, 0.0) : ",
joshualitt5ae5fc52014-07-29 12:59:27 -0700140 outColor);
Brian Osmanc4689632016-12-19 17:04:59 -0500141 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
Brian Salomon1d816b92017-08-17 11:07:59 -0400142 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700143 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700144 }
145 break;
146 }
147 case kRepeat_Mode: {
148 SkString clampedCoords;
jvanverth3fc65602015-07-22 08:41:51 -0700149 clampedCoords.printf("mod(%s - %s.xy, %s.zw - %s.xy) + %s.xy",
joshualitt5ae5fc52014-07-29 12:59:27 -0700150 inCoords.c_str(), fDomainName.c_str(), fDomainName.c_str(),
151 fDomainName.c_str(), fDomainName.c_str());
152
jvanverth3fc65602015-07-22 08:41:51 -0700153 builder->codeAppendf("%s = ", outColor);
Brian Osmanc4689632016-12-19 17:04:59 -0500154 builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
Brian Salomon1d816b92017-08-17 11:07:59 -0400155 kVec2f_GrSLType, colorXformHelper);
jvanverth3fc65602015-07-22 08:41:51 -0700156 builder->codeAppend(";");
joshualitt5ae5fc52014-07-29 12:59:27 -0700157 break;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000158 }
159 }
160}
161
egdaniel018fb622015-10-28 07:26:40 -0700162void GrTextureDomain::GLDomain::setData(const GrGLSLProgramDataManager& pdman,
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000163 const GrTextureDomain& textureDomain,
Robert Phillipsc686ce32017-07-21 14:12:29 -0400164 GrSurfaceProxy* proxy) {
165 GrTexture* tex = proxy->priv().peekTexture();
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000166 SkASSERT(textureDomain.mode() == fMode);
167 if (kIgnore_Mode != textureDomain.mode()) {
Robert Phillipse98234f2017-01-09 14:23:59 -0500168 SkScalar wInv = SK_Scalar1 / tex->width();
169 SkScalar hInv = SK_Scalar1 / tex->height();
170
egdaniel018fb622015-10-28 07:26:40 -0700171 float values[kPrevDomainCount] = {
Robert Phillipse98234f2017-01-09 14:23:59 -0500172 SkScalarToFloat(textureDomain.domain().fLeft * wInv),
173 SkScalarToFloat(textureDomain.domain().fTop * hInv),
174 SkScalarToFloat(textureDomain.domain().fRight * wInv),
175 SkScalarToFloat(textureDomain.domain().fBottom * hInv)
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000176 };
Robert Phillipse98234f2017-01-09 14:23:59 -0500177
178 SkASSERT(values[0] >= 0.0f && values[0] <= 1.0f);
179 SkASSERT(values[1] >= 0.0f && values[1] <= 1.0f);
180 SkASSERT(values[2] >= 0.0f && values[2] <= 1.0f);
181 SkASSERT(values[3] >= 0.0f && values[3] <= 1.0f);
182
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000183 // vertical flip if necessary
Robert Phillipsc686ce32017-07-21 14:12:29 -0400184 if (kBottomLeft_GrSurfaceOrigin == proxy->origin()) {
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000185 values[1] = 1.0f - values[1];
186 values[3] = 1.0f - values[3];
187 // The top and bottom were just flipped, so correct the ordering
188 // of elements so that values = (l, t, r, b).
189 SkTSwap(values[1], values[3]);
190 }
egdaniel018fb622015-10-28 07:26:40 -0700191 if (0 != memcmp(values, fPrevDomain, kPrevDomainCount * sizeof(float))) {
kkinnunen7510b222014-07-30 00:04:16 -0700192 pdman.set4fv(fDomainUni, 1, values);
egdaniel018fb622015-10-28 07:26:40 -0700193 memcpy(fPrevDomain, values, kPrevDomainCount * sizeof(float));
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000194 }
195 }
196}
197
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000198///////////////////////////////////////////////////////////////////////////////
Brian Salomon587e08f2017-01-27 10:59:27 -0500199inline GrFragmentProcessor::OptimizationFlags GrTextureDomainEffect::OptFlags(
Robert Phillips40fd7c92017-01-30 08:06:27 -0500200 GrPixelConfig config, GrTextureDomain::Mode mode) {
201 if (mode == GrTextureDomain::kDecal_Mode || !GrPixelConfigIsOpaque(config)) {
Brian Salomonf3b995b2017-02-15 10:22:23 -0500202 return GrFragmentProcessor::kCompatibleWithCoverageAsAlpha_OptimizationFlag;
Brian Salomon587e08f2017-01-27 10:59:27 -0500203 } else {
Brian Salomonf3b995b2017-02-15 10:22:23 -0500204 return GrFragmentProcessor::kCompatibleWithCoverageAsAlpha_OptimizationFlag |
Brian Salomon587e08f2017-01-27 10:59:27 -0500205 GrFragmentProcessor::kPreservesOpaqueInput_OptimizationFlag;
206 }
207}
208
Brian Salomonaff329b2017-08-11 09:40:37 -0400209std::unique_ptr<GrFragmentProcessor> GrTextureDomainEffect::Make(
210 sk_sp<GrTextureProxy> proxy,
211 sk_sp<GrColorSpaceXform> colorSpaceXform,
212 const SkMatrix& matrix,
213 const SkRect& domain,
214 GrTextureDomain::Mode mode,
215 GrSamplerParams::FilterMode filterMode) {
Robert Phillips40fd7c92017-01-30 08:06:27 -0500216 if (GrTextureDomain::kIgnore_Mode == mode ||
217 (GrTextureDomain::kClamp_Mode == mode && can_ignore_rect(proxy.get(), domain))) {
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400218 return GrSimpleTextureEffect::Make(std::move(proxy),
Robert Phillips296b1cc2017-03-15 10:42:12 -0400219 std::move(colorSpaceXform), matrix, filterMode);
Robert Phillips40fd7c92017-01-30 08:06:27 -0500220 } else {
Brian Salomonaff329b2017-08-11 09:40:37 -0400221 return std::unique_ptr<GrFragmentProcessor>(new GrTextureDomainEffect(
222 std::move(proxy), std::move(colorSpaceXform), matrix, domain, mode, filterMode));
Robert Phillips40fd7c92017-01-30 08:06:27 -0500223 }
224}
225
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400226GrTextureDomainEffect::GrTextureDomainEffect(sk_sp<GrTextureProxy> proxy,
Robert Phillips40fd7c92017-01-30 08:06:27 -0500227 sk_sp<GrColorSpaceXform> colorSpaceXform,
228 const SkMatrix& matrix,
229 const SkRect& domain,
230 GrTextureDomain::Mode mode,
231 GrSamplerParams::FilterMode filterMode)
Brian Salomon6cd51b52017-07-26 19:07:15 -0400232 : INHERITED(OptFlags(proxy->config(), mode))
233 , fCoordTransform(matrix, proxy.get())
234 , fTextureDomain(proxy.get(), domain, mode)
235 , fTextureSampler(std::move(proxy), filterMode)
236 , fColorSpaceXform(std::move(colorSpaceXform)) {
Robert Phillips40fd7c92017-01-30 08:06:27 -0500237 SkASSERT(mode != GrTextureDomain::kRepeat_Mode ||
238 filterMode == GrSamplerParams::kNone_FilterMode);
239 this->initClassID<GrTextureDomainEffect>();
Brian Salomon6cd51b52017-07-26 19:07:15 -0400240 this->addCoordTransform(&fCoordTransform);
241 this->addTextureSampler(&fTextureSampler);
Robert Phillips40fd7c92017-01-30 08:06:27 -0500242}
243
Brian Salomon3f6f9652017-07-28 07:34:05 -0400244GrTextureDomainEffect::GrTextureDomainEffect(const GrTextureDomainEffect& that)
245 : INHERITED(that.optimizationFlags())
246 , fCoordTransform(that.fCoordTransform)
247 , fTextureDomain(that.fTextureDomain)
248 , fTextureSampler(that.fTextureSampler)
249 , fColorSpaceXform(that.fColorSpaceXform) {
250 this->initClassID<GrTextureDomainEffect>();
251 this->addCoordTransform(&fCoordTransform);
252 this->addTextureSampler(&fTextureSampler);
253}
254
Brian Salomon94efbf52016-11-29 13:43:05 -0500255void GrTextureDomainEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800256 GrProcessorKeyBuilder* b) const {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400257 b->add32(GrTextureDomain::GLDomain::DomainKey(fTextureDomain));
Brian Osman70826d72016-12-20 15:06:18 -0500258 b->add32(GrColorSpaceXform::XformKey(this->colorSpaceXform()));
joshualitteb2a6762014-12-04 11:35:33 -0800259}
260
egdaniel57d3b032015-11-13 11:57:27 -0800261GrGLSLFragmentProcessor* GrTextureDomainEffect::onCreateGLSLInstance() const {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400262 class GLSLProcessor : public GrGLSLFragmentProcessor {
263 public:
264 void emitCode(EmitArgs& args) override {
265 const GrTextureDomainEffect& tde = args.fFp.cast<GrTextureDomainEffect>();
266 const GrTextureDomain& domain = tde.fTextureDomain;
267
268 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
269 SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
Brian Osmanc4689632016-12-19 17:04:59 -0500270
Brian Osmanc624d9d2017-03-08 11:42:02 -0500271 fColorSpaceHelper.emitCode(args.fUniformHandler, tde.colorSpaceXform());
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400272 fGLDomain.sampleTexture(fragBuilder,
273 args.fUniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500274 args.fShaderCaps,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400275 domain,
276 args.fOutputColor,
277 coords2D,
278 args.fTexSamplers[0],
Brian Osmanc4689632016-12-19 17:04:59 -0500279 args.fInputColor,
Brian Osmanc624d9d2017-03-08 11:42:02 -0500280 &fColorSpaceHelper);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400281 }
282
283 protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400284 void onSetData(const GrGLSLProgramDataManager& pdman,
285 const GrFragmentProcessor& fp) override {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400286 const GrTextureDomainEffect& tde = fp.cast<GrTextureDomainEffect>();
287 const GrTextureDomain& domain = tde.fTextureDomain;
Robert Phillipsc686ce32017-07-21 14:12:29 -0400288 GrSurfaceProxy* proxy = tde.textureSampler(0).proxy();
Robert Phillips9bee2e52017-05-29 12:37:20 -0400289
Robert Phillipsc686ce32017-07-21 14:12:29 -0400290 fGLDomain.setData(pdman, domain, proxy);
Brian Osmanc4689632016-12-19 17:04:59 -0500291 if (SkToBool(tde.colorSpaceXform())) {
Brian Osmanc624d9d2017-03-08 11:42:02 -0500292 fColorSpaceHelper.setData(pdman, tde.colorSpaceXform());
Brian Osmanc4689632016-12-19 17:04:59 -0500293 }
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400294 }
295
296 private:
297 GrTextureDomain::GLDomain fGLDomain;
Brian Osmanc624d9d2017-03-08 11:42:02 -0500298 GrGLSLColorSpaceXformHelper fColorSpaceHelper;
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400299 };
300
301 return new GLSLProcessor;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000302}
303
bsalomon0e08fc12014-10-15 08:19:04 -0700304bool GrTextureDomainEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
joshualitt49586be2014-09-16 08:21:41 -0700305 const GrTextureDomainEffect& s = sBase.cast<GrTextureDomainEffect>();
Brian Salomona7c4c292016-11-17 12:47:06 -0500306 return this->fTextureDomain == s.fTextureDomain;
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000307}
308
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000309///////////////////////////////////////////////////////////////////////////////
310
joshualittb0a8a372014-09-23 09:50:21 -0700311GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrTextureDomainEffect);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000312
Hal Canary6f6961e2017-01-31 13:50:44 -0500313#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -0400314std::unique_ptr<GrFragmentProcessor> GrTextureDomainEffect::TestCreate(GrProcessorTestData* d) {
Robert Phillips40fd7c92017-01-30 08:06:27 -0500315 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
316 : GrProcessorUnitTest::kAlphaTextureIdx;
317 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000318 SkRect domain;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500319 domain.fLeft = d->fRandom->nextRangeScalar(0, proxy->width());
320 domain.fRight = d->fRandom->nextRangeScalar(domain.fLeft, proxy->width());
321 domain.fTop = d->fRandom->nextRangeScalar(0, proxy->height());
322 domain.fBottom = d->fRandom->nextRangeScalar(domain.fTop, proxy->height());
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000323 GrTextureDomain::Mode mode =
joshualitt0067ff52015-07-08 14:26:19 -0700324 (GrTextureDomain::Mode) d->fRandom->nextULessThan(GrTextureDomain::kModeCount);
325 const SkMatrix& matrix = GrTest::TestMatrix(d->fRandom);
326 bool bilerp = mode != GrTextureDomain::kRepeat_Mode ? d->fRandom->nextBool() : false;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500327 sk_sp<GrColorSpaceXform> colorSpaceXform = GrTest::TestColorXform(d->fRandom);
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400328 return GrTextureDomainEffect::Make(std::move(proxy),
Robert Phillips40fd7c92017-01-30 08:06:27 -0500329 std::move(colorSpaceXform),
330 matrix,
331 domain,
332 mode,
333 bilerp ? GrSamplerParams::kBilerp_FilterMode
334 : GrSamplerParams::kNone_FilterMode);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400335}
Hal Canary6f6961e2017-01-31 13:50:44 -0500336#endif
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400337
338///////////////////////////////////////////////////////////////////////////////
Brian Salomonaff329b2017-08-11 09:40:37 -0400339std::unique_ptr<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::Make(
340 sk_sp<GrTextureProxy> proxy, const SkIRect& subset, const SkIPoint& deviceSpaceOffset) {
341 return std::unique_ptr<GrFragmentProcessor>(new GrDeviceSpaceTextureDecalFragmentProcessor(
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400342 std::move(proxy), subset, deviceSpaceOffset));
Robert Phillips40fd7c92017-01-30 08:06:27 -0500343}
344
345GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400346 sk_sp<GrTextureProxy> proxy,
347 const SkIRect& subset,
348 const SkIPoint& deviceSpaceOffset)
Brian Salomonf3b995b2017-02-15 10:22:23 -0500349 : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400350 , fTextureSampler(proxy, GrSamplerParams::ClampNoFilter())
Robert Phillips40fd7c92017-01-30 08:06:27 -0500351 , fTextureDomain(proxy.get(), GrTextureDomain::MakeTexelDomain(subset),
352 GrTextureDomain::kDecal_Mode) {
353 this->addTextureSampler(&fTextureSampler);
354 fDeviceSpaceOffset.fX = deviceSpaceOffset.fX - subset.fLeft;
355 fDeviceSpaceOffset.fY = deviceSpaceOffset.fY - subset.fTop;
356 this->initClassID<GrDeviceSpaceTextureDecalFragmentProcessor>();
357}
358
Brian Salomon1a2a7ab2017-07-26 13:11:51 -0400359GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
360 const GrDeviceSpaceTextureDecalFragmentProcessor& that)
361 : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
362 , fTextureSampler(that.fTextureSampler)
363 , fTextureDomain(that.fTextureDomain)
364 , fDeviceSpaceOffset(that.fDeviceSpaceOffset) {
365 this->initClassID<GrDeviceSpaceTextureDecalFragmentProcessor>();
366 this->addTextureSampler(&fTextureSampler);
367}
368
Brian Salomonaff329b2017-08-11 09:40:37 -0400369std::unique_ptr<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::clone() const {
370 return std::unique_ptr<GrFragmentProcessor>(
371 new GrDeviceSpaceTextureDecalFragmentProcessor(*this));
Brian Salomon1a2a7ab2017-07-26 13:11:51 -0400372}
373
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400374GrGLSLFragmentProcessor* GrDeviceSpaceTextureDecalFragmentProcessor::onCreateGLSLInstance() const {
375 class GLSLProcessor : public GrGLSLFragmentProcessor {
376 public:
377 void emitCode(EmitArgs& args) override {
378 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
379 args.fFp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
380 const char* scaleAndTranslateName;
381 fScaleAndTranslateUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
Brian Salomon1d816b92017-08-17 11:07:59 -0400382 kVec4f_GrSLType,
383 kDefault_GrSLPrecision,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400384 "scaleAndTranslate",
385 &scaleAndTranslateName);
Brian Salomon1d816b92017-08-17 11:07:59 -0400386 args.fFragBuilder->codeAppendf("float2 coords = sk_FragCoord.xy * %s.xy + %s.zw;",
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400387 scaleAndTranslateName, scaleAndTranslateName);
388 fGLDomain.sampleTexture(args.fFragBuilder,
389 args.fUniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500390 args.fShaderCaps,
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400391 dstdfp.fTextureDomain,
392 args.fOutputColor,
393 SkString("coords"),
394 args.fTexSamplers[0],
395 args.fInputColor);
396 }
397
398 protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400399 void onSetData(const GrGLSLProgramDataManager& pdman,
400 const GrFragmentProcessor& fp) override {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400401 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
402 fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
Robert Phillipsc686ce32017-07-21 14:12:29 -0400403 GrSurfaceProxy* proxy = dstdfp.textureSampler(0).proxy();
404 GrTexture* texture = proxy->priv().peekTexture();
Robert Phillips9bee2e52017-05-29 12:37:20 -0400405
Robert Phillipsc686ce32017-07-21 14:12:29 -0400406 fGLDomain.setData(pdman, dstdfp.fTextureDomain, proxy);
Brian Salomon0bbecb22016-11-17 11:38:22 -0500407 float iw = 1.f / texture->width();
408 float ih = 1.f / texture->height();
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400409 float scaleAndTransData[4] = {
410 iw, ih,
411 -dstdfp.fDeviceSpaceOffset.fX * iw, -dstdfp.fDeviceSpaceOffset.fY * ih
412 };
Robert Phillipsc686ce32017-07-21 14:12:29 -0400413 if (proxy->origin() == kBottomLeft_GrSurfaceOrigin) {
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400414 scaleAndTransData[1] = -scaleAndTransData[1];
415 scaleAndTransData[3] = 1 - scaleAndTransData[3];
416 }
417 pdman.set4fv(fScaleAndTranslateUni, 1, scaleAndTransData);
418 }
419
420 private:
421 GrTextureDomain::GLDomain fGLDomain;
422 UniformHandle fScaleAndTranslateUni;
423 };
424
425 return new GLSLProcessor;
426}
427
428bool GrDeviceSpaceTextureDecalFragmentProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
429 const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
430 fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
Brian Salomon1a2a7ab2017-07-26 13:11:51 -0400431 return dstdfp.fTextureSampler.proxy()->underlyingUniqueID() ==
432 fTextureSampler.proxy()->underlyingUniqueID() &&
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400433 dstdfp.fDeviceSpaceOffset == fDeviceSpaceOffset &&
434 dstdfp.fTextureDomain == fTextureDomain;
435}
436
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400437///////////////////////////////////////////////////////////////////////////////
438
439GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDeviceSpaceTextureDecalFragmentProcessor);
440
Hal Canary6f6961e2017-01-31 13:50:44 -0500441#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -0400442std::unique_ptr<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::TestCreate(
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400443 GrProcessorTestData* d) {
444 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
445 : GrProcessorUnitTest::kAlphaTextureIdx;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500446 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400447 SkIRect subset;
Robert Phillips40fd7c92017-01-30 08:06:27 -0500448 subset.fLeft = d->fRandom->nextULessThan(proxy->width() - 1);
449 subset.fRight = d->fRandom->nextRangeU(subset.fLeft, proxy->width());
450 subset.fTop = d->fRandom->nextULessThan(proxy->height() - 1);
451 subset.fBottom = d->fRandom->nextRangeU(subset.fTop, proxy->height());
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400452 SkIPoint pt;
453 pt.fX = d->fRandom->nextULessThan(2048);
454 pt.fY = d->fRandom->nextULessThan(2048);
Robert Phillipsfbcef6e2017-06-15 12:07:18 -0400455 return GrDeviceSpaceTextureDecalFragmentProcessor::Make(std::move(proxy), subset, pt);
commit-bot@chromium.org907fbd52013-12-09 17:03:02 +0000456}
Hal Canary6f6961e2017-01-31 13:50:44 -0500457#endif