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

          Line data    Source code
       1             : /*
       2             :  * Copyright 2016 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 "GrTextureProducer.h"
       9             : #include "GrClip.h"
      10             : #include "GrRenderTargetContext.h"
      11             : #include "GrResourceProvider.h"
      12             : #include "GrSurfaceProxy.h"
      13             : #include "GrSurfaceProxyPriv.h"
      14             : #include "GrTexture.h"
      15             : #include "effects/GrBicubicEffect.h"
      16             : #include "effects/GrSimpleTextureEffect.h"
      17             : #include "effects/GrTextureDomain.h"
      18             : 
      19           0 : sk_sp<GrTextureProxy> GrTextureProducer::CopyOnGpu(GrContext* context,
      20             :                                                    sk_sp<GrTextureProxy> inputProxy,
      21             :                                                    const SkIRect* subset,
      22             :                                                    const CopyParams& copyParams) {
      23           0 :     SkASSERT(!subset || !subset->isEmpty());
      24           0 :     SkASSERT(context);
      25             : 
      26           0 :     GrPixelConfig config = GrMakePixelConfigUncompressed(inputProxy->config());
      27             : 
      28           0 :     const SkRect dstRect = SkRect::MakeIWH(copyParams.fWidth, copyParams.fHeight);
      29             : 
      30             :     sk_sp<GrRenderTargetContext> copyRTC = context->makeRenderTargetContextWithFallback(
      31           0 :         SkBackingFit::kExact, dstRect.width(), dstRect.height(), config, nullptr);
      32           0 :     if (!copyRTC) {
      33           0 :         return nullptr;
      34             :     }
      35             : 
      36           0 :     GrPaint paint;
      37           0 :     paint.setGammaCorrect(true);
      38             : 
      39             :     SkRect localRect;
      40           0 :     if (subset) {
      41           0 :         localRect = SkRect::Make(*subset);
      42             :     } else {
      43           0 :         localRect = SkRect::MakeWH(inputProxy->width(), inputProxy->height());
      44             :     }
      45             : 
      46           0 :     bool needsDomain = false;
      47           0 :     if (copyParams.fFilter != GrSamplerParams::kNone_FilterMode) {
      48           0 :         bool resizing = localRect.width()  != dstRect.width() ||
      49           0 :                         localRect.height() != dstRect.height();
      50             : 
      51           0 :         if (GrResourceProvider::IsFunctionallyExact(inputProxy.get())) {
      52           0 :             needsDomain = subset && resizing;
      53             :         } else {
      54           0 :             needsDomain = resizing;
      55             :         }
      56             :     }
      57             : 
      58           0 :     if (needsDomain) {
      59           0 :         const SkRect domain = localRect.makeInset(0.5f, 0.5f);
      60             :         // This would cause us to read values from outside the subset. Surely, the caller knows
      61             :         // better!
      62           0 :         SkASSERT(copyParams.fFilter != GrSamplerParams::kMipMap_FilterMode);
      63             :         paint.addColorFragmentProcessor(
      64           0 :             GrTextureDomainEffect::Make(context->resourceProvider(), std::move(inputProxy),
      65             :                                         nullptr, SkMatrix::I(),
      66           0 :                                         domain, GrTextureDomain::kClamp_Mode, copyParams.fFilter));
      67             :     } else {
      68           0 :         GrSamplerParams params(SkShader::kClamp_TileMode, copyParams.fFilter);
      69           0 :         paint.addColorTextureProcessor(context->resourceProvider(), std::move(inputProxy),
      70           0 :                                        nullptr, SkMatrix::I(), params);
      71             :     }
      72           0 :     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
      73             : 
      74           0 :     copyRTC->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect,
      75           0 :                             localRect);
      76           0 :     return copyRTC->asTextureProxyRef();
      77             : }
      78             : 
      79             : /** Determines whether a texture domain is necessary and if so what domain to use. There are two
      80             :  *  rectangles to consider:
      81             :  *  - The first is the content area specified by the texture adjuster (i.e., textureContentArea).
      82             :  *    We can *never* allow filtering to cause bleed of pixels outside this rectangle.
      83             :  *  - The second rectangle is the constraint rectangle (i.e., constraintRect), which is known to
      84             :  *    be contained by the content area. The filterConstraint specifies whether we are allowed to
      85             :  *    bleed across this rect.
      86             :  *
      87             :  *  We want to avoid using a domain if possible. We consider the above rectangles, the filter type,
      88             :  *  and whether the coords generated by the draw would all fall within the constraint rect. If the
      89             :  *  latter is true we only need to consider whether the filter would extend beyond the rects.
      90             :  */
      91           0 : GrTextureProducer::DomainMode GrTextureProducer::DetermineDomainMode(
      92             :                                 const SkRect& constraintRect,
      93             :                                 FilterConstraint filterConstraint,
      94             :                                 bool coordsLimitedToConstraintRect,
      95             :                                 GrTextureProxy* proxy,
      96             :                                 const SkIRect* contentRect,
      97             :                                 const GrSamplerParams::FilterMode* filterModeOrNullForBicubic,
      98             :                                 SkRect* domainRect) {
      99           0 :     const SkIRect proxyBounds = SkIRect::MakeWH(proxy->width(), proxy->height());
     100             : 
     101           0 :     SkASSERT(proxyBounds.contains(constraintRect));
     102             :     // We only expect a content area rect if there is some non-content area.
     103           0 :     SkASSERT(!contentRect ||
     104             :              (!contentRect->contains(proxyBounds) &&
     105             :               proxyBounds.contains(*contentRect) &&
     106             :               contentRect->contains(constraintRect)));
     107             : 
     108           0 :     const bool proxyIsExact = GrResourceProvider::IsFunctionallyExact(proxy);
     109             : 
     110             :     // If the constraint rectangle contains the whole proxy then no need for a domain.
     111           0 :     if (constraintRect.contains(proxyBounds) && proxyIsExact) {
     112           0 :         return kNoDomain_DomainMode;
     113             :     }
     114             : 
     115           0 :     if (!contentRect && !proxyIsExact) {
     116           0 :         contentRect = &proxyBounds;
     117             :     }
     118             : 
     119           0 :     bool restrictFilterToRect = (filterConstraint == GrTextureProducer::kYes_FilterConstraint);
     120             : 
     121             :     // If we can filter outside the constraint rect, and there is no non-content area of the
     122             :     // proxy, and we aren't going to generate sample coords outside the constraint rect then we
     123             :     // don't need a domain.
     124           0 :     if (!restrictFilterToRect && !contentRect && coordsLimitedToConstraintRect) {
     125           0 :         return kNoDomain_DomainMode;
     126             :     }
     127             : 
     128             :     // Get the domain inset based on sampling mode (or bail if mipped)
     129           0 :     SkScalar filterHalfWidth = 0.f;
     130           0 :     if (filterModeOrNullForBicubic) {
     131           0 :         switch (*filterModeOrNullForBicubic) {
     132             :             case GrSamplerParams::kNone_FilterMode:
     133           0 :                 if (coordsLimitedToConstraintRect) {
     134           0 :                     return kNoDomain_DomainMode;
     135             :                 } else {
     136           0 :                     filterHalfWidth = 0.f;
     137             :                 }
     138           0 :                 break;
     139             :             case GrSamplerParams::kBilerp_FilterMode:
     140           0 :                 filterHalfWidth = .5f;
     141           0 :                 break;
     142             :             case GrSamplerParams::kMipMap_FilterMode:
     143           0 :                 if (restrictFilterToRect || contentRect) {
     144             :                     // No domain can save us here.
     145           0 :                     return kTightCopy_DomainMode;
     146             :                 }
     147           0 :                 return kNoDomain_DomainMode;
     148             :         }
     149             :     } else {
     150             :         // bicubic does nearest filtering internally.
     151           0 :         filterHalfWidth = 1.5f;
     152             :     }
     153             : 
     154             :     // Both bilerp and bicubic use bilinear filtering and so need to be clamped to the center
     155             :     // of the edge texel. Pinning to the texel center has no impact on nearest mode and MIP-maps
     156             : 
     157             :     static const SkScalar kDomainInset = 0.5f;
     158             :     // Figure out the limits of pixels we're allowed to sample from.
     159             :     // Unless we know the amount of outset and the texture matrix we have to conservatively enforce
     160             :     // the domain.
     161           0 :     if (restrictFilterToRect) {
     162           0 :         *domainRect = constraintRect.makeInset(kDomainInset, kDomainInset);
     163           0 :     } else if (contentRect) {
     164             :         // If we got here then: there is a contentRect, the coords are limited to the
     165             :         // constraint rect, and we're allowed to filter across the constraint rect boundary. So
     166             :         // we check whether the filter would reach across the edge of the content area.
     167             :         // We will only set the sides that are required.
     168             : 
     169           0 :         domainRect->setLargest();
     170           0 :         if (coordsLimitedToConstraintRect) {
     171             :             // We may be able to use the fact that the texture coords are limited to the constraint
     172             :             // rect in order to avoid having to add a domain.
     173           0 :             bool needContentAreaConstraint = false;
     174           0 :             if (contentRect->fLeft > 0 &&
     175           0 :                 contentRect->fLeft + filterHalfWidth > constraintRect.fLeft) {
     176           0 :                 domainRect->fLeft = contentRect->fLeft + kDomainInset;
     177           0 :                 needContentAreaConstraint = true;
     178             :             }
     179           0 :             if (contentRect->fTop > 0 &&
     180           0 :                 contentRect->fTop + filterHalfWidth > constraintRect.fTop) {
     181           0 :                 domainRect->fTop = contentRect->fTop + kDomainInset;
     182           0 :                 needContentAreaConstraint = true;
     183             :             }
     184           0 :             if ((!proxyIsExact || contentRect->fRight < proxy->width()) &&
     185           0 :                 contentRect->fRight - filterHalfWidth < constraintRect.fRight) {
     186           0 :                 domainRect->fRight = contentRect->fRight - kDomainInset;
     187           0 :                 needContentAreaConstraint = true;
     188             :             }
     189           0 :             if ((!proxyIsExact || contentRect->fBottom < proxy->height()) &&
     190           0 :                 contentRect->fBottom - filterHalfWidth < constraintRect.fBottom) {
     191           0 :                 domainRect->fBottom = contentRect->fBottom - kDomainInset;
     192           0 :                 needContentAreaConstraint = true;
     193             :             }
     194           0 :             if (!needContentAreaConstraint) {
     195           0 :                 return kNoDomain_DomainMode;
     196             :             }
     197             :         } else {
     198             :             // Our sample coords for the texture are allowed to be outside the constraintRect so we
     199             :             // don't consider it when computing the domain.
     200           0 :             if (contentRect->fLeft > 0) {
     201           0 :                 domainRect->fLeft = contentRect->fLeft + kDomainInset;
     202             :             }
     203           0 :             if (contentRect->fTop > 0) {
     204           0 :                 domainRect->fTop = contentRect->fTop + kDomainInset;
     205             :             }
     206           0 :             if (!proxyIsExact || contentRect->fRight < proxy->width()) {
     207           0 :                 domainRect->fRight = contentRect->fRight - kDomainInset;
     208             :             }
     209           0 :             if (!proxyIsExact || contentRect->fBottom < proxy->height()) {
     210           0 :                 domainRect->fBottom = contentRect->fBottom - kDomainInset;
     211             :             }
     212             :         }
     213             :     } else {
     214           0 :         return kNoDomain_DomainMode;
     215             :     }
     216             : 
     217           0 :     if (domainRect->fLeft > domainRect->fRight) {
     218           0 :         domainRect->fLeft = domainRect->fRight = SkScalarAve(domainRect->fLeft, domainRect->fRight);
     219             :     }
     220           0 :     if (domainRect->fTop > domainRect->fBottom) {
     221           0 :         domainRect->fTop = domainRect->fBottom = SkScalarAve(domainRect->fTop, domainRect->fBottom);
     222             :     }
     223           0 :     return kDomain_DomainMode;
     224             : }
     225             : 
     226           0 : sk_sp<GrFragmentProcessor> GrTextureProducer::CreateFragmentProcessorForDomainAndFilter(
     227             :                                         GrResourceProvider* resourceProvider,
     228             :                                         sk_sp<GrTextureProxy> proxy,
     229             :                                         sk_sp<GrColorSpaceXform> colorSpaceXform,
     230             :                                         const SkMatrix& textureMatrix,
     231             :                                         DomainMode domainMode,
     232             :                                         const SkRect& domain,
     233             :                                         const GrSamplerParams::FilterMode* filterOrNullForBicubic) {
     234           0 :     SkASSERT(kTightCopy_DomainMode != domainMode);
     235           0 :     if (filterOrNullForBicubic) {
     236           0 :         if (kDomain_DomainMode == domainMode) {
     237           0 :             return GrTextureDomainEffect::Make(resourceProvider, std::move(proxy),
     238           0 :                                                std::move(colorSpaceXform), textureMatrix,
     239             :                                                domain, GrTextureDomain::kClamp_Mode,
     240           0 :                                                *filterOrNullForBicubic);
     241             :         } else {
     242           0 :             GrSamplerParams params(SkShader::kClamp_TileMode, *filterOrNullForBicubic);
     243           0 :             return GrSimpleTextureEffect::Make(resourceProvider, std::move(proxy),
     244           0 :                                                std::move(colorSpaceXform), textureMatrix,
     245           0 :                                                params);
     246             :         }
     247             :     } else {
     248           0 :         if (kDomain_DomainMode == domainMode) {
     249           0 :             return GrBicubicEffect::Make(resourceProvider, std::move(proxy),
     250           0 :                                          std::move(colorSpaceXform),
     251           0 :                                          textureMatrix, domain);
     252             :         } else {
     253             :             static const SkShader::TileMode kClampClamp[] =
     254             :                 { SkShader::kClamp_TileMode, SkShader::kClamp_TileMode };
     255           0 :             return GrBicubicEffect::Make(resourceProvider, std::move(proxy),
     256           0 :                                          std::move(colorSpaceXform),
     257           0 :                                          textureMatrix, kClampClamp);
     258             :         }
     259             :     }
     260             : }

Generated by: LCOV version 1.13