diff options
author | Robert Phillips <robertphillips@google.com> | 2017-03-27 10:14:08 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-03-27 14:57:56 +0000 |
commit | 51e7ca31cedc821d2317930d91c5a7dd10cb8735 (patch) | |
tree | 5663cc073e3a769953cd9482096894000a1523db /src/gpu/GrTextureProducer.cpp | |
parent | 59eed0db9909c4a097f5929e1a12bc53552ac6fb (diff) |
Add new proxy-based DetermineDomainMode w/ test
split out of: https://skia-review.googlesource.com/c/8823/ (Remove GrFragmentProcessor-derived class' GrTexture-based ctors)
Change-Id: Ibf54da589710382254b416e4801d83e9f5663f44
Reviewed-on: https://skia-review.googlesource.com/10180
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src/gpu/GrTextureProducer.cpp')
-rw-r--r-- | src/gpu/GrTextureProducer.cpp | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/gpu/GrTextureProducer.cpp b/src/gpu/GrTextureProducer.cpp index 41f689ae17..a8390ee9bc 100644 --- a/src/gpu/GrTextureProducer.cpp +++ b/src/gpu/GrTextureProducer.cpp @@ -266,6 +266,141 @@ GrTextureProducer::DomainMode GrTextureProducer::DetermineDomainMode( return kDomain_DomainMode; } +GrTextureProducer::DomainMode GrTextureProducer::DetermineDomainMode( + const SkRect& constraintRect, + FilterConstraint filterConstraint, + bool coordsLimitedToConstraintRect, + GrTextureProxy* proxy, + const SkIRect* contentRect, + const GrSamplerParams::FilterMode* filterModeOrNullForBicubic, + SkRect* domainRect) { + const SkIRect proxyBounds = SkIRect::MakeWH(proxy->width(), proxy->height()); + + SkASSERT(proxyBounds.contains(constraintRect)); + // We only expect a content area rect if there is some non-content area. + SkASSERT(!contentRect || + (!contentRect->contains(proxyBounds) && + proxyBounds.contains(*contentRect) && + contentRect->contains(constraintRect))); + + const bool proxyIsExact = GrResourceProvider::IsFunctionallyExact(proxy); + + // If the constraint rectangle contains the whole proxy then no need for a domain. + if (constraintRect.contains(proxyBounds) && proxyIsExact) { + return kNoDomain_DomainMode; + } + + if (!contentRect && !proxyIsExact) { + contentRect = &proxyBounds; + } + + bool restrictFilterToRect = (filterConstraint == GrTextureProducer::kYes_FilterConstraint); + + // If we can filter outside the constraint rect, and there is no non-content area of the + // proxy, and we aren't going to generate sample coords outside the constraint rect then we + // don't need a domain. + if (!restrictFilterToRect && !contentRect && coordsLimitedToConstraintRect) { + return kNoDomain_DomainMode; + } + + // Get the domain inset based on sampling mode (or bail if mipped) + SkScalar filterHalfWidth = 0.f; + if (filterModeOrNullForBicubic) { + switch (*filterModeOrNullForBicubic) { + case GrSamplerParams::kNone_FilterMode: + if (coordsLimitedToConstraintRect) { + return kNoDomain_DomainMode; + } else { + filterHalfWidth = 0.f; + } + break; + case GrSamplerParams::kBilerp_FilterMode: + filterHalfWidth = .5f; + break; + case GrSamplerParams::kMipMap_FilterMode: + if (restrictFilterToRect || contentRect) { + // No domain can save us here. + return kTightCopy_DomainMode; + } + return kNoDomain_DomainMode; + } + } else { + // bicubic does nearest filtering internally. + filterHalfWidth = 1.5f; + } + + // Both bilerp and bicubic use bilinear filtering and so need to be clamped to the center + // of the edge texel. Pinning to the texel center has no impact on nearest mode and MIP-maps + + static const SkScalar kDomainInset = 0.5f; + // Figure out the limits of pixels we're allowed to sample from. + // Unless we know the amount of outset and the texture matrix we have to conservatively enforce + // the domain. + if (restrictFilterToRect) { + *domainRect = constraintRect.makeInset(kDomainInset, kDomainInset); + } else if (contentRect) { + // If we got here then: there is a contentRect, the coords are limited to the + // constraint rect, and we're allowed to filter across the constraint rect boundary. So + // we check whether the filter would reach across the edge of the content area. + // We will only set the sides that are required. + + domainRect->setLargest(); + if (coordsLimitedToConstraintRect) { + // We may be able to use the fact that the texture coords are limited to the constraint + // rect in order to avoid having to add a domain. + bool needContentAreaConstraint = false; + if (contentRect->fLeft > 0 && + contentRect->fLeft + filterHalfWidth > constraintRect.fLeft) { + domainRect->fLeft = contentRect->fLeft + kDomainInset; + needContentAreaConstraint = true; + } + if (contentRect->fTop > 0 && + contentRect->fTop + filterHalfWidth > constraintRect.fTop) { + domainRect->fTop = contentRect->fTop + kDomainInset; + needContentAreaConstraint = true; + } + if ((!proxyIsExact || contentRect->fRight < proxy->width()) && + contentRect->fRight - filterHalfWidth < constraintRect.fRight) { + domainRect->fRight = contentRect->fRight - kDomainInset; + needContentAreaConstraint = true; + } + if ((!proxyIsExact || contentRect->fBottom < proxy->height()) && + contentRect->fBottom - filterHalfWidth < constraintRect.fBottom) { + domainRect->fBottom = contentRect->fBottom - kDomainInset; + needContentAreaConstraint = true; + } + if (!needContentAreaConstraint) { + return kNoDomain_DomainMode; + } + } else { + // Our sample coords for the texture are allowed to be outside the constraintRect so we + // don't consider it when computing the domain. + if (contentRect->fLeft > 0) { + domainRect->fLeft = contentRect->fLeft + kDomainInset; + } + if (contentRect->fTop > 0) { + domainRect->fTop = contentRect->fTop + kDomainInset; + } + if (!proxyIsExact || contentRect->fRight < proxy->width()) { + domainRect->fRight = contentRect->fRight - kDomainInset; + } + if (!proxyIsExact || contentRect->fBottom < proxy->height()) { + domainRect->fBottom = contentRect->fBottom - kDomainInset; + } + } + } else { + return kNoDomain_DomainMode; + } + + if (domainRect->fLeft > domainRect->fRight) { + domainRect->fLeft = domainRect->fRight = SkScalarAve(domainRect->fLeft, domainRect->fRight); + } + if (domainRect->fTop > domainRect->fBottom) { + domainRect->fTop = domainRect->fBottom = SkScalarAve(domainRect->fTop, domainRect->fBottom); + } + return kDomain_DomainMode; +} + sk_sp<GrFragmentProcessor> GrTextureProducer::CreateFragmentProcessorForDomainAndFilter( GrTexture* texture, sk_sp<GrColorSpaceXform> colorSpaceXform, |