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

          Line data    Source code
       1             : /*
       2             :  * Copyright 2014 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 "GrBicubicEffect.h"
       9             : 
      10             : #include "GrProxyMove.h"
      11             : #include "GrTextureProxy.h"
      12             : #include "glsl/GrGLSLColorSpaceXformHelper.h"
      13             : #include "glsl/GrGLSLFragmentShaderBuilder.h"
      14             : #include "glsl/GrGLSLProgramDataManager.h"
      15             : #include "glsl/GrGLSLUniformHandler.h"
      16             : #include "../private/GrGLSL.h"
      17             : 
      18           0 : class GrGLBicubicEffect : public GrGLSLFragmentProcessor {
      19             : public:
      20             :     void emitCode(EmitArgs&) override;
      21             : 
      22           0 :     static inline void GenKey(const GrProcessor& effect, const GrShaderCaps&,
      23             :                               GrProcessorKeyBuilder* b) {
      24           0 :         const GrBicubicEffect& bicubicEffect = effect.cast<GrBicubicEffect>();
      25           0 :         b->add32(GrTextureDomain::GLDomain::DomainKey(bicubicEffect.domain()));
      26           0 :         b->add32(GrColorSpaceXform::XformKey(bicubicEffect.colorSpaceXform()));
      27           0 :     }
      28             : 
      29             : protected:
      30             :     void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
      31             : 
      32             : private:
      33             :     typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
      34             : 
      35             :     UniformHandle               fImageIncrementUni;
      36             :     GrGLSLColorSpaceXformHelper fColorSpaceHelper;
      37             :     GrTextureDomain::GLDomain   fDomain;
      38             : 
      39             :     typedef GrGLSLFragmentProcessor INHERITED;
      40             : };
      41             : 
      42           0 : void GrGLBicubicEffect::emitCode(EmitArgs& args) {
      43           0 :     const GrBicubicEffect& bicubicEffect = args.fFp.cast<GrBicubicEffect>();
      44             : 
      45           0 :     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
      46             :     fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
      47             :                                                     kVec2f_GrSLType, kDefault_GrSLPrecision,
      48           0 :                                                     "ImageIncrement");
      49             : 
      50           0 :     const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
      51             : 
      52           0 :     fColorSpaceHelper.emitCode(uniformHandler, bicubicEffect.colorSpaceXform());
      53             : 
      54           0 :     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
      55           0 :     SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
      56             : 
      57             :     /*
      58             :      * Filter weights come from Don Mitchell & Arun Netravali's 'Reconstruction Filters in Computer
      59             :      * Graphics', ACM SIGGRAPH Computer Graphics 22, 4 (Aug. 1988).
      60             :      * ACM DL: http://dl.acm.org/citation.cfm?id=378514
      61             :      * Free  : http://www.cs.utexas.edu/users/fussell/courses/cs384g/lectures/mitchell/Mitchell.pdf
      62             :      *
      63             :      * The authors define a family of cubic filters with two free parameters (B and C):
      64             :      *
      65             :      *            { (12 - 9B - 6C)|x|^3 + (-18 + 12B + 6C)|x|^2 + (6 - 2B)          if |x| < 1
      66             :      * k(x) = 1/6 { (-B - 6C)|x|^3 + (6B + 30C)|x|^2 + (-12B - 48C)|x| + (8B + 24C) if 1 <= |x| < 2
      67             :      *            { 0                                                               otherwise
      68             :      *
      69             :      * Various well-known cubic splines can be generated, and the authors select (1/3, 1/3) as their
      70             :      * favorite overall spline - this is now commonly known as the Mitchell filter, and is the
      71             :      * source of the specific weights below.
      72             :      *
      73             :      * This is GLSL, so the matrix is column-major (transposed from standard matrix notation).
      74             :      */
      75           0 :     fragBuilder->codeAppend("mat4 kMitchellCoefficients = mat4("
      76             :                             " 1.0 / 18.0,  16.0 / 18.0,   1.0 / 18.0,  0.0 / 18.0,"
      77             :                             "-9.0 / 18.0,   0.0 / 18.0,   9.0 / 18.0,  0.0 / 18.0,"
      78             :                             "15.0 / 18.0, -36.0 / 18.0,  27.0 / 18.0, -6.0 / 18.0,"
      79           0 :                             "-7.0 / 18.0,  21.0 / 18.0, -21.0 / 18.0,  7.0 / 18.0);");
      80           0 :     fragBuilder->codeAppendf("vec2 coord = %s - %s * vec2(0.5);", coords2D.c_str(), imgInc);
      81             :     // We unnormalize the coord in order to determine our fractional offset (f) within the texel
      82             :     // We then snap coord to a texel center and renormalize. The snap prevents cases where the
      83             :     // starting coords are near a texel boundary and accumulations of imgInc would cause us to skip/
      84             :     // double hit a texel.
      85           0 :     fragBuilder->codeAppendf("coord /= %s;", imgInc);
      86           0 :     fragBuilder->codeAppend("vec2 f = fract(coord);");
      87           0 :     fragBuilder->codeAppendf("coord = (coord - f + vec2(0.5)) * %s;", imgInc);
      88           0 :     fragBuilder->codeAppend("vec4 wx = kMitchellCoefficients * vec4(1.0, f.x, f.x * f.x, f.x * f.x * f.x);");
      89           0 :     fragBuilder->codeAppend("vec4 wy = kMitchellCoefficients * vec4(1.0, f.y, f.y * f.y, f.y * f.y * f.y);");
      90           0 :     fragBuilder->codeAppend("vec4 rowColors[4];");
      91           0 :     for (int y = 0; y < 4; ++y) {
      92           0 :         for (int x = 0; x < 4; ++x) {
      93           0 :             SkString coord;
      94           0 :             coord.printf("coord + %s * vec2(%d, %d)", imgInc, x - 1, y - 1);
      95           0 :             SkString sampleVar;
      96           0 :             sampleVar.printf("rowColors[%d]", x);
      97           0 :             fDomain.sampleTexture(fragBuilder,
      98             :                                   args.fUniformHandler,
      99             :                                   args.fShaderCaps,
     100             :                                   bicubicEffect.domain(),
     101             :                                   sampleVar.c_str(),
     102             :                                   coord,
     103           0 :                                   args.fTexSamplers[0]);
     104             :         }
     105           0 :         fragBuilder->codeAppendf(
     106             :             "vec4 s%d = wx.x * rowColors[0] + wx.y * rowColors[1] + wx.z * rowColors[2] + wx.w * rowColors[3];",
     107           0 :             y);
     108             :     }
     109           0 :     SkString bicubicColor("(wy.x * s0 + wy.y * s1 + wy.z * s2 + wy.w * s3)");
     110           0 :     if (fColorSpaceHelper.isValid()) {
     111           0 :         SkString xformedColor;
     112           0 :         fragBuilder->appendColorGamutXform(&xformedColor, bicubicColor.c_str(), &fColorSpaceHelper);
     113           0 :         bicubicColor.swap(xformedColor);
     114             :     }
     115           0 :     fragBuilder->codeAppendf("%s = %s;",
     116           0 :                              args.fOutputColor, (GrGLSLExpr4(bicubicColor.c_str()) *
     117           0 :                                                  GrGLSLExpr4(args.fInputColor)).c_str());
     118           0 : }
     119             : 
     120           0 : void GrGLBicubicEffect::onSetData(const GrGLSLProgramDataManager& pdman,
     121             :                                   const GrFragmentProcessor& processor) {
     122           0 :     const GrBicubicEffect& bicubicEffect = processor.cast<GrBicubicEffect>();
     123           0 :     GrTexture* texture = processor.textureSampler(0).texture();
     124             :     float imageIncrement[2];
     125           0 :     imageIncrement[0] = 1.0f / texture->width();
     126           0 :     imageIncrement[1] = 1.0f / texture->height();
     127           0 :     pdman.set2fv(fImageIncrementUni, 1, imageIncrement);
     128           0 :     fDomain.setData(pdman, bicubicEffect.domain(), texture);
     129           0 :     if (SkToBool(bicubicEffect.colorSpaceXform())) {
     130           0 :         fColorSpaceHelper.setData(pdman, bicubicEffect.colorSpaceXform());
     131             :     }
     132           0 : }
     133             : 
     134           0 : GrBicubicEffect::GrBicubicEffect(GrResourceProvider* resourceProvider, sk_sp<GrTextureProxy> proxy,
     135             :                                  sk_sp<GrColorSpaceXform> colorSpaceXform,
     136             :                                  const SkMatrix &matrix,
     137           0 :                                  const SkShader::TileMode tileModes[2])
     138             :   : INHERITED{resourceProvider,
     139           0 :               ModulationFlags(proxy->config()),
     140           0 :               GR_PROXY_MOVE(proxy),
     141           0 :               std::move(colorSpaceXform),
     142             :               matrix,
     143           0 :               GrSamplerParams(tileModes, GrSamplerParams::kNone_FilterMode)}
     144           0 :   , fDomain(GrTextureDomain::IgnoredDomain()) {
     145           0 :     this->initClassID<GrBicubicEffect>();
     146           0 : }
     147             : 
     148           0 : GrBicubicEffect::GrBicubicEffect(GrResourceProvider* resourceProvider, sk_sp<GrTextureProxy> proxy,
     149             :                                  sk_sp<GrColorSpaceXform> colorSpaceXform,
     150             :                                  const SkMatrix &matrix,
     151           0 :                                  const SkRect& domain)
     152           0 :   : INHERITED(resourceProvider, ModulationFlags(proxy->config()), proxy,
     153           0 :               std::move(colorSpaceXform), matrix,
     154           0 :               GrSamplerParams(SkShader::kClamp_TileMode, GrSamplerParams::kNone_FilterMode))
     155           0 :   , fDomain(proxy.get(), domain, GrTextureDomain::kClamp_Mode) {
     156           0 :     this->initClassID<GrBicubicEffect>();
     157           0 : }
     158             : 
     159           0 : GrBicubicEffect::~GrBicubicEffect() {
     160           0 : }
     161             : 
     162           0 : void GrBicubicEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
     163             :                                             GrProcessorKeyBuilder* b) const {
     164           0 :     GrGLBicubicEffect::GenKey(*this, caps, b);
     165           0 : }
     166             : 
     167           0 : GrGLSLFragmentProcessor* GrBicubicEffect::onCreateGLSLInstance() const  {
     168           0 :     return new GrGLBicubicEffect;
     169             : }
     170             : 
     171           0 : bool GrBicubicEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
     172           0 :     const GrBicubicEffect& s = sBase.cast<GrBicubicEffect>();
     173           0 :     return fDomain == s.fDomain;
     174             : }
     175             : 
     176             : GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrBicubicEffect);
     177             : 
     178             : #if GR_TEST_UTILS
     179           0 : sk_sp<GrFragmentProcessor> GrBicubicEffect::TestCreate(GrProcessorTestData* d) {
     180           0 :     int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
     181           0 :                                         : GrProcessorUnitTest::kAlphaTextureIdx;
     182           0 :     sk_sp<GrColorSpaceXform> colorSpaceXform = GrTest::TestColorXform(d->fRandom);
     183             :     static const SkShader::TileMode kClampClamp[] =
     184             :         { SkShader::kClamp_TileMode, SkShader::kClamp_TileMode };
     185             :     return GrBicubicEffect::Make(d->resourceProvider(),
     186           0 :                                  d->textureProxy(texIdx), std::move(colorSpaceXform),
     187           0 :                                  SkMatrix::I(), kClampClamp);
     188             : }
     189             : #endif
     190             : 
     191             : //////////////////////////////////////////////////////////////////////////////
     192             : 
     193           0 : bool GrBicubicEffect::ShouldUseBicubic(const SkMatrix& matrix,
     194             :                                        GrSamplerParams::FilterMode* filterMode) {
     195           0 :     if (matrix.isIdentity()) {
     196           0 :         *filterMode = GrSamplerParams::kNone_FilterMode;
     197           0 :         return false;
     198             :     }
     199             : 
     200             :     SkScalar scales[2];
     201           0 :     if (!matrix.getMinMaxScales(scales) || scales[0] < SK_Scalar1) {
     202             :         // Bicubic doesn't handle arbitrary minimization well, as src texels can be skipped
     203             :         // entirely,
     204           0 :         *filterMode = GrSamplerParams::kMipMap_FilterMode;
     205           0 :         return false;
     206             :     }
     207             :     // At this point if scales[1] == SK_Scalar1 then the matrix doesn't do any scaling.
     208           0 :     if (scales[1] == SK_Scalar1) {
     209           0 :         if (matrix.rectStaysRect() && SkScalarIsInt(matrix.getTranslateX()) &&
     210           0 :             SkScalarIsInt(matrix.getTranslateY())) {
     211           0 :             *filterMode = GrSamplerParams::kNone_FilterMode;
     212             :         } else {
     213             :             // Use bilerp to handle rotation or fractional translation.
     214           0 :             *filterMode = GrSamplerParams::kBilerp_FilterMode;
     215             :         }
     216           0 :         return false;
     217             :     }
     218             :     // When we use the bicubic filtering effect each sample is read from the texture using
     219             :     // nearest neighbor sampling.
     220           0 :     *filterMode = GrSamplerParams::kNone_FilterMode;
     221           0 :     return true;
     222             : }

Generated by: LCOV version 1.13