LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/effects - GrTextureDomain.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 234 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 28 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       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"
       9             : 
      10             : #include "GrResourceProvider.h"
      11             : #include "GrShaderCaps.h"
      12             : #include "GrSimpleTextureEffect.h"
      13             : #include "GrSurfaceProxyPriv.h"
      14             : #include "SkFloatingPoint.h"
      15             : #include "glsl/GrGLSLColorSpaceXformHelper.h"
      16             : #include "glsl/GrGLSLFragmentProcessor.h"
      17             : #include "glsl/GrGLSLFragmentShaderBuilder.h"
      18             : #include "glsl/GrGLSLProgramDataManager.h"
      19             : #include "glsl/GrGLSLShaderBuilder.h"
      20             : #include "glsl/GrGLSLUniformHandler.h"
      21             : 
      22           0 : static bool can_ignore_rect(GrTextureProxy* proxy, const SkRect& domain) {
      23           0 :     if (GrResourceProvider::IsFunctionallyExact(proxy)) {
      24           0 :         const SkIRect kFullRect = SkIRect::MakeWH(proxy->width(), proxy->height());
      25             : 
      26           0 :         return domain.contains(kFullRect);
      27             :     }
      28             : 
      29           0 :     return false;
      30             : }
      31             : 
      32           0 : static bool can_ignore_rect(GrTexture* tex, const SkRect& domain) {
      33             :     // This logic is relying on the instantiated size of 'tex'. In the deferred world it
      34             :     // will have to change so this logic only fires for kExact texture proxies. This shouldn't
      35             :     // change the actual behavior of Ganesh since shaders shouldn't be accessing pixels outside
      36             :     // of the content rectangle.
      37           0 :     const SkIRect kFullRect = SkIRect::MakeWH(tex->width(), tex->height());
      38             : 
      39           0 :     return domain.contains(kFullRect);
      40             : }
      41             : 
      42           0 : GrTextureDomain::GrTextureDomain(GrTexture* tex, const SkRect& domain, Mode mode, int index)
      43             :     : fMode(mode)
      44           0 :     , fIndex(index) {
      45             : 
      46           0 :     if (kIgnore_Mode == fMode) {
      47           0 :         return;
      48             :     }
      49             : 
      50           0 :     if (kClamp_Mode == mode && can_ignore_rect(tex, domain)) {
      51           0 :         fMode = kIgnore_Mode;
      52           0 :         return;
      53             :     }
      54             : 
      55           0 :     const SkRect kFullRect = SkRect::MakeIWH(tex->width(), tex->height());
      56             : 
      57             :     // We don't currently handle domains that are empty or don't intersect the texture.
      58             :     // It is OK if the domain rect is a line or point, but it should not be inverted. We do not
      59             :     // handle rects that do not intersect the [0..1]x[0..1] rect.
      60           0 :     SkASSERT(domain.fLeft <= domain.fRight);
      61           0 :     SkASSERT(domain.fTop <= domain.fBottom);
      62           0 :     fDomain.fLeft = SkScalarPin(domain.fLeft, 0.0f, kFullRect.fRight);
      63           0 :     fDomain.fRight = SkScalarPin(domain.fRight, fDomain.fLeft, kFullRect.fRight);
      64           0 :     fDomain.fTop = SkScalarPin(domain.fTop, 0.0f, kFullRect.fBottom);
      65           0 :     fDomain.fBottom = SkScalarPin(domain.fBottom, fDomain.fTop, kFullRect.fBottom);
      66           0 :     SkASSERT(fDomain.fLeft <= fDomain.fRight);
      67           0 :     SkASSERT(fDomain.fTop <= fDomain.fBottom);
      68             : }
      69             : 
      70           0 : GrTextureDomain::GrTextureDomain(GrTextureProxy* proxy, const SkRect& domain, Mode mode, int index)
      71             :     : fMode(mode)
      72           0 :     , fIndex(index) {
      73             : 
      74           0 :     if (kIgnore_Mode == fMode) {
      75           0 :         return;
      76             :     }
      77             : 
      78           0 :     if (kClamp_Mode == mode && can_ignore_rect(proxy, domain)) {
      79           0 :         fMode = kIgnore_Mode;
      80           0 :         return;
      81             :     }
      82             : 
      83           0 :     const SkRect kFullRect = SkRect::MakeIWH(proxy->width(), proxy->height());
      84             : 
      85             :     // We don't currently handle domains that are empty or don't intersect the texture.
      86             :     // It is OK if the domain rect is a line or point, but it should not be inverted. We do not
      87             :     // handle rects that do not intersect the [0..1]x[0..1] rect.
      88           0 :     SkASSERT(domain.fLeft <= domain.fRight);
      89           0 :     SkASSERT(domain.fTop <= domain.fBottom);
      90           0 :     fDomain.fLeft = SkScalarPin(domain.fLeft, 0.0f, kFullRect.fRight);
      91           0 :     fDomain.fRight = SkScalarPin(domain.fRight, fDomain.fLeft, kFullRect.fRight);
      92           0 :     fDomain.fTop = SkScalarPin(domain.fTop, 0.0f, kFullRect.fBottom);
      93           0 :     fDomain.fBottom = SkScalarPin(domain.fBottom, fDomain.fTop, kFullRect.fBottom);
      94           0 :     SkASSERT(fDomain.fLeft <= fDomain.fRight);
      95           0 :     SkASSERT(fDomain.fTop <= fDomain.fBottom);
      96             : }
      97             : 
      98             : //////////////////////////////////////////////////////////////////////////////
      99             : 
     100           0 : void GrTextureDomain::GLDomain::sampleTexture(GrGLSLShaderBuilder* builder,
     101             :                                               GrGLSLUniformHandler* uniformHandler,
     102             :                                               const GrShaderCaps* shaderCaps,
     103             :                                               const GrTextureDomain& textureDomain,
     104             :                                               const char* outColor,
     105             :                                               const SkString& inCoords,
     106             :                                               GrGLSLFragmentProcessor::SamplerHandle sampler,
     107             :                                               const char* inModulateColor,
     108             :                                               GrGLSLColorSpaceXformHelper* colorXformHelper) {
     109           0 :     SkASSERT((Mode)-1 == fMode || textureDomain.mode() == fMode);
     110           0 :     SkDEBUGCODE(fMode = textureDomain.mode();)
     111             : 
     112           0 :     if (textureDomain.mode() != kIgnore_Mode && !fDomainUni.isValid()) {
     113             :         const char* name;
     114           0 :         SkString uniName("TexDom");
     115           0 :         if (textureDomain.fIndex >= 0) {
     116           0 :             uniName.appendS32(textureDomain.fIndex);
     117             :         }
     118             :         fDomainUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
     119             :                                                 kVec4f_GrSLType, kDefault_GrSLPrecision,
     120           0 :                                                 uniName.c_str(), &name);
     121           0 :         fDomainName = name;
     122             :     }
     123             : 
     124           0 :     switch (textureDomain.mode()) {
     125             :         case kIgnore_Mode: {
     126           0 :             builder->codeAppendf("%s = ", outColor);
     127           0 :             builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
     128           0 :                                                     kVec2f_GrSLType, colorXformHelper);
     129           0 :             builder->codeAppend(";");
     130           0 :             break;
     131             :         }
     132             :         case kClamp_Mode: {
     133           0 :             SkString clampedCoords;
     134           0 :             clampedCoords.appendf("clamp(%s, %s.xy, %s.zw)",
     135           0 :                                   inCoords.c_str(), fDomainName.c_str(), fDomainName.c_str());
     136             : 
     137           0 :             builder->codeAppendf("%s = ", outColor);
     138           0 :             builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
     139           0 :                                                     kVec2f_GrSLType, colorXformHelper);
     140           0 :             builder->codeAppend(";");
     141           0 :             break;
     142             :         }
     143             :         case kDecal_Mode: {
     144             :             // Add a block since we're going to declare variables.
     145           0 :             GrGLSLShaderBuilder::ShaderBlock block(builder);
     146             : 
     147           0 :             const char* domain = fDomainName.c_str();
     148           0 :             if (!shaderCaps->canUseAnyFunctionInShader()) {
     149             :                 // On the NexusS and GalaxyNexus, the other path (with the 'any'
     150             :                 // call) causes the compilation error "Calls to any function that
     151             :                 // may require a gradient calculation inside a conditional block
     152             :                 // may return undefined results". This appears to be an issue with
     153             :                 // the 'any' call since even the simple "result=black; if (any())
     154             :                 // result=white;" code fails to compile.
     155           0 :                 builder->codeAppend("vec4 outside = vec4(0.0, 0.0, 0.0, 0.0);");
     156           0 :                 builder->codeAppend("vec4 inside = ");
     157           0 :                 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
     158           0 :                                                         kVec2f_GrSLType, colorXformHelper);
     159           0 :                 builder->codeAppend(";");
     160             : 
     161           0 :                 builder->codeAppendf("highp float x = (%s).x;", inCoords.c_str());
     162           0 :                 builder->codeAppendf("highp float y = (%s).y;", inCoords.c_str());
     163             : 
     164             :                 builder->codeAppendf("x = abs(2.0*(x - %s.x)/(%s.z - %s.x) - 1.0);",
     165           0 :                                      domain, domain, domain);
     166             :                 builder->codeAppendf("y = abs(2.0*(y - %s.y)/(%s.w - %s.y) - 1.0);",
     167           0 :                                      domain, domain, domain);
     168           0 :                 builder->codeAppend("float blend = step(1.0, max(x, y));");
     169           0 :                 builder->codeAppendf("%s = mix(inside, outside, blend);", outColor);
     170             :             } else {
     171           0 :                 builder->codeAppend("bvec4 outside;\n");
     172           0 :                 builder->codeAppendf("outside.xy = lessThan(%s, %s.xy);", inCoords.c_str(),
     173           0 :                                        domain);
     174           0 :                 builder->codeAppendf("outside.zw = greaterThan(%s, %s.zw);", inCoords.c_str(),
     175           0 :                                        domain);
     176             :                 builder->codeAppendf("%s = any(outside) ? vec4(0.0, 0.0, 0.0, 0.0) : ",
     177           0 :                                        outColor);
     178           0 :                 builder->appendTextureLookupAndModulate(inModulateColor, sampler, inCoords.c_str(),
     179           0 :                                                         kVec2f_GrSLType, colorXformHelper);
     180           0 :                 builder->codeAppend(";");
     181             :             }
     182           0 :             break;
     183             :         }
     184             :         case kRepeat_Mode: {
     185           0 :             SkString clampedCoords;
     186           0 :             clampedCoords.printf("mod(%s - %s.xy, %s.zw - %s.xy) + %s.xy",
     187             :                                  inCoords.c_str(), fDomainName.c_str(), fDomainName.c_str(),
     188           0 :                                  fDomainName.c_str(), fDomainName.c_str());
     189             : 
     190           0 :             builder->codeAppendf("%s = ", outColor);
     191           0 :             builder->appendTextureLookupAndModulate(inModulateColor, sampler, clampedCoords.c_str(),
     192           0 :                                                     kVec2f_GrSLType, colorXformHelper);
     193           0 :             builder->codeAppend(";");
     194           0 :             break;
     195             :         }
     196             :     }
     197           0 : }
     198             : 
     199           0 : void GrTextureDomain::GLDomain::setData(const GrGLSLProgramDataManager& pdman,
     200             :                                         const GrTextureDomain& textureDomain,
     201             :                                         GrTexture* tex) {
     202           0 :     SkASSERT(textureDomain.mode() == fMode);
     203           0 :     if (kIgnore_Mode != textureDomain.mode()) {
     204           0 :         SkScalar wInv = SK_Scalar1 / tex->width();
     205           0 :         SkScalar hInv = SK_Scalar1 / tex->height();
     206             : 
     207             :         float values[kPrevDomainCount] = {
     208           0 :             SkScalarToFloat(textureDomain.domain().fLeft * wInv),
     209           0 :             SkScalarToFloat(textureDomain.domain().fTop * hInv),
     210           0 :             SkScalarToFloat(textureDomain.domain().fRight * wInv),
     211           0 :             SkScalarToFloat(textureDomain.domain().fBottom * hInv)
     212           0 :         };
     213             : 
     214           0 :         SkASSERT(values[0] >= 0.0f && values[0] <= 1.0f);
     215           0 :         SkASSERT(values[1] >= 0.0f && values[1] <= 1.0f);
     216           0 :         SkASSERT(values[2] >= 0.0f && values[2] <= 1.0f);
     217           0 :         SkASSERT(values[3] >= 0.0f && values[3] <= 1.0f);
     218             : 
     219             :         // vertical flip if necessary
     220           0 :         if (kBottomLeft_GrSurfaceOrigin == tex->origin()) {
     221           0 :             values[1] = 1.0f - values[1];
     222           0 :             values[3] = 1.0f - values[3];
     223             :             // The top and bottom were just flipped, so correct the ordering
     224             :             // of elements so that values = (l, t, r, b).
     225           0 :             SkTSwap(values[1], values[3]);
     226             :         }
     227           0 :         if (0 != memcmp(values, fPrevDomain, kPrevDomainCount * sizeof(float))) {
     228           0 :             pdman.set4fv(fDomainUni, 1, values);
     229           0 :             memcpy(fPrevDomain, values, kPrevDomainCount * sizeof(float));
     230             :         }
     231             :     }
     232           0 : }
     233             : 
     234             : ///////////////////////////////////////////////////////////////////////////////
     235           0 : inline GrFragmentProcessor::OptimizationFlags GrTextureDomainEffect::OptFlags(
     236             :         GrPixelConfig config, GrTextureDomain::Mode mode) {
     237           0 :     if (mode == GrTextureDomain::kDecal_Mode || !GrPixelConfigIsOpaque(config)) {
     238           0 :         return GrFragmentProcessor::kCompatibleWithCoverageAsAlpha_OptimizationFlag;
     239             :     } else {
     240             :         return GrFragmentProcessor::kCompatibleWithCoverageAsAlpha_OptimizationFlag |
     241           0 :                GrFragmentProcessor::kPreservesOpaqueInput_OptimizationFlag;
     242             :     }
     243             : }
     244             : 
     245           0 : sk_sp<GrFragmentProcessor> GrTextureDomainEffect::Make(GrResourceProvider* resourceProvider,
     246             :                                                        sk_sp<GrTextureProxy> proxy,
     247             :                                                        sk_sp<GrColorSpaceXform> colorSpaceXform,
     248             :                                                        const SkMatrix& matrix,
     249             :                                                        const SkRect& domain,
     250             :                                                        GrTextureDomain::Mode mode,
     251             :                                                        GrSamplerParams::FilterMode filterMode) {
     252           0 :     if (GrTextureDomain::kIgnore_Mode == mode ||
     253           0 :         (GrTextureDomain::kClamp_Mode == mode && can_ignore_rect(proxy.get(), domain))) {
     254           0 :         return GrSimpleTextureEffect::Make(resourceProvider, std::move(proxy),
     255           0 :                                            std::move(colorSpaceXform), matrix, filterMode);
     256             :     } else {
     257             :         return sk_sp<GrFragmentProcessor>(
     258           0 :             new GrTextureDomainEffect(resourceProvider, std::move(proxy),
     259           0 :                                       std::move(colorSpaceXform),
     260           0 :                                       matrix, domain, mode, filterMode));
     261             :     }
     262             : }
     263             : 
     264           0 : GrTextureDomainEffect::GrTextureDomainEffect(GrResourceProvider* resourceProvider,
     265             :                                              sk_sp<GrTextureProxy> proxy,
     266             :                                              sk_sp<GrColorSpaceXform> colorSpaceXform,
     267             :                                              const SkMatrix& matrix,
     268             :                                              const SkRect& domain,
     269             :                                              GrTextureDomain::Mode mode,
     270           0 :                                              GrSamplerParams::FilterMode filterMode)
     271           0 :     : GrSingleTextureEffect(resourceProvider, OptFlags(proxy->config(), mode), proxy,
     272           0 :                             std::move(colorSpaceXform), matrix, filterMode)
     273           0 :     , fTextureDomain(proxy.get(), domain, mode) {
     274           0 :     SkASSERT(mode != GrTextureDomain::kRepeat_Mode ||
     275             :              filterMode == GrSamplerParams::kNone_FilterMode);
     276           0 :     this->initClassID<GrTextureDomainEffect>();
     277           0 : }
     278             : 
     279           0 : void GrTextureDomainEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
     280             :                                                   GrProcessorKeyBuilder* b) const {
     281           0 :     b->add32(GrTextureDomain::GLDomain::DomainKey(fTextureDomain));
     282           0 :     b->add32(GrColorSpaceXform::XformKey(this->colorSpaceXform()));
     283           0 : }
     284             : 
     285           0 : GrGLSLFragmentProcessor* GrTextureDomainEffect::onCreateGLSLInstance() const  {
     286           0 :     class GLSLProcessor : public GrGLSLFragmentProcessor {
     287             :     public:
     288           0 :         void emitCode(EmitArgs& args) override {
     289           0 :             const GrTextureDomainEffect& tde = args.fFp.cast<GrTextureDomainEffect>();
     290           0 :             const GrTextureDomain& domain = tde.fTextureDomain;
     291             : 
     292           0 :             GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     293           0 :             SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
     294             : 
     295           0 :             fColorSpaceHelper.emitCode(args.fUniformHandler, tde.colorSpaceXform());
     296           0 :             fGLDomain.sampleTexture(fragBuilder,
     297             :                                     args.fUniformHandler,
     298             :                                     args.fShaderCaps,
     299             :                                     domain,
     300             :                                     args.fOutputColor,
     301             :                                     coords2D,
     302           0 :                                     args.fTexSamplers[0],
     303             :                                     args.fInputColor,
     304           0 :                                     &fColorSpaceHelper);
     305           0 :         }
     306             : 
     307             :     protected:
     308           0 :         void onSetData(const GrGLSLProgramDataManager& pdman,
     309             :                        const GrFragmentProcessor& fp) override {
     310           0 :             const GrTextureDomainEffect& tde = fp.cast<GrTextureDomainEffect>();
     311           0 :             const GrTextureDomain& domain = tde.fTextureDomain;
     312           0 :             fGLDomain.setData(pdman, domain, tde.textureSampler(0).texture());
     313           0 :             if (SkToBool(tde.colorSpaceXform())) {
     314           0 :                 fColorSpaceHelper.setData(pdman, tde.colorSpaceXform());
     315             :             }
     316           0 :         }
     317             : 
     318             :     private:
     319             :         GrTextureDomain::GLDomain         fGLDomain;
     320             :         GrGLSLColorSpaceXformHelper       fColorSpaceHelper;
     321             :     };
     322             : 
     323           0 :     return new GLSLProcessor;
     324             : }
     325             : 
     326           0 : bool GrTextureDomainEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
     327           0 :     const GrTextureDomainEffect& s = sBase.cast<GrTextureDomainEffect>();
     328           0 :     return this->fTextureDomain == s.fTextureDomain;
     329             : }
     330             : 
     331             : ///////////////////////////////////////////////////////////////////////////////
     332             : 
     333             : GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrTextureDomainEffect);
     334             : 
     335             : #if GR_TEST_UTILS
     336           0 : sk_sp<GrFragmentProcessor> GrTextureDomainEffect::TestCreate(GrProcessorTestData* d) {
     337           0 :     int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
     338           0 :                                         : GrProcessorUnitTest::kAlphaTextureIdx;
     339           0 :     sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
     340             :     SkRect domain;
     341           0 :     domain.fLeft = d->fRandom->nextRangeScalar(0, proxy->width());
     342           0 :     domain.fRight = d->fRandom->nextRangeScalar(domain.fLeft, proxy->width());
     343           0 :     domain.fTop = d->fRandom->nextRangeScalar(0, proxy->height());
     344           0 :     domain.fBottom = d->fRandom->nextRangeScalar(domain.fTop, proxy->height());
     345             :     GrTextureDomain::Mode mode =
     346           0 :         (GrTextureDomain::Mode) d->fRandom->nextULessThan(GrTextureDomain::kModeCount);
     347           0 :     const SkMatrix& matrix = GrTest::TestMatrix(d->fRandom);
     348           0 :     bool bilerp = mode != GrTextureDomain::kRepeat_Mode ? d->fRandom->nextBool() : false;
     349           0 :     sk_sp<GrColorSpaceXform> colorSpaceXform = GrTest::TestColorXform(d->fRandom);
     350             :     return GrTextureDomainEffect::Make(d->resourceProvider(),
     351           0 :                                        std::move(proxy),
     352           0 :                                        std::move(colorSpaceXform),
     353             :                                        matrix,
     354             :                                        domain,
     355             :                                        mode,
     356             :                                        bilerp ? GrSamplerParams::kBilerp_FilterMode
     357           0 :                                               : GrSamplerParams::kNone_FilterMode);
     358             : }
     359             : #endif
     360             : 
     361             : ///////////////////////////////////////////////////////////////////////////////
     362           0 : sk_sp<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::Make(
     363             :         GrResourceProvider* resourceProvider,
     364             :         sk_sp<GrTextureProxy> proxy,
     365             :         const SkIRect& subset,
     366             :         const SkIPoint& deviceSpaceOffset) {
     367             :     return sk_sp<GrFragmentProcessor>(new GrDeviceSpaceTextureDecalFragmentProcessor(
     368           0 :             resourceProvider, std::move(proxy), subset, deviceSpaceOffset));
     369             : }
     370             : 
     371           0 : GrDeviceSpaceTextureDecalFragmentProcessor::GrDeviceSpaceTextureDecalFragmentProcessor(
     372             :         GrResourceProvider* resourceProvider,
     373             :         sk_sp<GrTextureProxy> proxy,
     374             :         const SkIRect& subset,
     375           0 :         const SkIPoint& deviceSpaceOffset)
     376             :         : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
     377             :         , fTextureSampler(resourceProvider, proxy, GrSamplerParams::ClampNoFilter())
     378           0 :         , fTextureDomain(proxy.get(), GrTextureDomain::MakeTexelDomain(subset),
     379           0 :                          GrTextureDomain::kDecal_Mode) {
     380           0 :     this->addTextureSampler(&fTextureSampler);
     381           0 :     fDeviceSpaceOffset.fX = deviceSpaceOffset.fX - subset.fLeft;
     382           0 :     fDeviceSpaceOffset.fY = deviceSpaceOffset.fY - subset.fTop;
     383           0 :     this->initClassID<GrDeviceSpaceTextureDecalFragmentProcessor>();
     384           0 : }
     385             : 
     386           0 : GrGLSLFragmentProcessor* GrDeviceSpaceTextureDecalFragmentProcessor::onCreateGLSLInstance() const  {
     387           0 :     class GLSLProcessor : public GrGLSLFragmentProcessor {
     388             :     public:
     389           0 :         void emitCode(EmitArgs& args) override {
     390             :             const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
     391           0 :                     args.fFp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
     392             :             const char* scaleAndTranslateName;
     393           0 :             fScaleAndTranslateUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
     394             :                                                                      kVec4f_GrSLType,
     395             :                                                                      kDefault_GrSLPrecision,
     396             :                                                                      "scaleAndTranslate",
     397           0 :                                                                      &scaleAndTranslateName);
     398           0 :             args.fFragBuilder->codeAppendf("vec2 coords = sk_FragCoord.xy * %s.xy + %s.zw;",
     399           0 :                                            scaleAndTranslateName, scaleAndTranslateName);
     400           0 :             fGLDomain.sampleTexture(args.fFragBuilder,
     401             :                                     args.fUniformHandler,
     402             :                                     args.fShaderCaps,
     403             :                                     dstdfp.fTextureDomain,
     404             :                                     args.fOutputColor,
     405           0 :                                     SkString("coords"),
     406           0 :                                     args.fTexSamplers[0],
     407           0 :                                     args.fInputColor);
     408           0 :         }
     409             : 
     410             :     protected:
     411           0 :         void onSetData(const GrGLSLProgramDataManager& pdman,
     412             :                        const GrFragmentProcessor& fp) override {
     413             :             const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
     414           0 :                     fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
     415           0 :             GrTexture* texture = dstdfp.textureSampler(0).texture();
     416           0 :             fGLDomain.setData(pdman, dstdfp.fTextureDomain, texture);
     417           0 :             float iw = 1.f / texture->width();
     418           0 :             float ih = 1.f / texture->height();
     419             :             float scaleAndTransData[4] = {
     420             :                 iw, ih,
     421           0 :                 -dstdfp.fDeviceSpaceOffset.fX * iw, -dstdfp.fDeviceSpaceOffset.fY * ih
     422           0 :             };
     423           0 :             if (texture->origin() == kBottomLeft_GrSurfaceOrigin) {
     424           0 :                 scaleAndTransData[1] = -scaleAndTransData[1];
     425           0 :                 scaleAndTransData[3] = 1 - scaleAndTransData[3];
     426             :             }
     427           0 :             pdman.set4fv(fScaleAndTranslateUni, 1, scaleAndTransData);
     428           0 :         }
     429             : 
     430             :     private:
     431             :         GrTextureDomain::GLDomain   fGLDomain;
     432             :         UniformHandle               fScaleAndTranslateUni;
     433             :     };
     434             : 
     435           0 :     return new GLSLProcessor;
     436             : }
     437             : 
     438           0 : bool GrDeviceSpaceTextureDecalFragmentProcessor::onIsEqual(const GrFragmentProcessor& fp) const {
     439             :     const GrDeviceSpaceTextureDecalFragmentProcessor& dstdfp =
     440           0 :             fp.cast<GrDeviceSpaceTextureDecalFragmentProcessor>();
     441           0 :     return dstdfp.fTextureSampler.texture() == fTextureSampler.texture() &&
     442           0 :            dstdfp.fDeviceSpaceOffset == fDeviceSpaceOffset &&
     443           0 :            dstdfp.fTextureDomain == fTextureDomain;
     444             : }
     445             : 
     446             : ///////////////////////////////////////////////////////////////////////////////
     447             : 
     448             : GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDeviceSpaceTextureDecalFragmentProcessor);
     449             : 
     450             : #if GR_TEST_UTILS
     451           0 : sk_sp<GrFragmentProcessor> GrDeviceSpaceTextureDecalFragmentProcessor::TestCreate(
     452             :         GrProcessorTestData* d) {
     453           0 :     int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
     454           0 :                                         : GrProcessorUnitTest::kAlphaTextureIdx;
     455           0 :     sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
     456             :     SkIRect subset;
     457           0 :     subset.fLeft = d->fRandom->nextULessThan(proxy->width() - 1);
     458           0 :     subset.fRight = d->fRandom->nextRangeU(subset.fLeft, proxy->width());
     459           0 :     subset.fTop = d->fRandom->nextULessThan(proxy->height() - 1);
     460           0 :     subset.fBottom = d->fRandom->nextRangeU(subset.fTop, proxy->height());
     461             :     SkIPoint pt;
     462           0 :     pt.fX = d->fRandom->nextULessThan(2048);
     463           0 :     pt.fY = d->fRandom->nextULessThan(2048);
     464             :     return GrDeviceSpaceTextureDecalFragmentProcessor::Make(d->resourceProvider(),
     465           0 :                                                             std::move(proxy), subset, pt);
     466             : }
     467             : #endif

Generated by: LCOV version 1.13