Chromium Code Reviews| Index: src/gpu/GrTextureParamsAdjuster.cpp |
| diff --git a/src/gpu/GrTextureParamsAdjuster.cpp b/src/gpu/GrTextureParamsAdjuster.cpp |
| index 579cf96ef36d30823a70b491cc0015e6813be116..d3daafc0932e6d1bff9d6aea2a47d528878f2ee0 100644 |
| --- a/src/gpu/GrTextureParamsAdjuster.cpp |
| +++ b/src/gpu/GrTextureParamsAdjuster.cpp |
| @@ -19,6 +19,7 @@ |
| #include "SkCanvas.h" |
| #include "SkGr.h" |
| #include "SkGrPriv.h" |
| +#include "effects/GrBicubicEffect.h" |
| #include "effects/GrTextureDomain.h" |
| typedef GrTextureProducer::CopyParams CopyParams; |
| @@ -171,6 +172,176 @@ GrTexture* GrTextureAdjuster::refTextureSafeForParams(const GrTextureParams& par |
| return result; |
| } |
| +enum DomainMode { |
| + kNoDomain_DomainMode, |
| + kDomain_DomainMode, |
| + kTightCopy_DomainMode |
| +}; |
| + |
| +/** Determines whether a texture domain is necessary and if so what domain to use. In the case of |
| + mip maps it may indicate that a copy must be made to avoid filtering outside the constraint |
| + rectangle or the content area of the texture. */ |
| +static DomainMode determine_domain_mode( |
|
robertphillips
2015/11/05 20:13:24
tab these over one to avoid lining up with the cod
bsalomon
2015/11/06 15:24:26
Done.
|
| + const SkRect& constraintRect, |
| + GrTextureAdjuster::FilterConstraint filterConstraint, |
| + bool coordsLimitedContraintRect, |
| + int texW, int texH, |
| + const SkIRect* textureContentArea, |
| + const GrTextureParams::FilterMode* filterModeOrNullForBicubic, |
| + SkRect* domainRect) { |
|
robertphillips
2015/11/05 20:13:24
... or maybe a '\n' here ?
bsalomon
2015/11/06 15:24:26
Done.
|
| + SkASSERT(SkRect::MakeIWH(texW, texH).contains(constraintRect)); |
| + // We only expect a content area rect if there is some non-content area. |
| + SkASSERT(!textureContentArea || |
| + (!textureContentArea->contains(SkIRect::MakeWH(texW, texH)) && |
| + SkRect::Make(*textureContentArea).contains(constraintRect))); |
| + |
| + SkRect textureBounds = SkRect::MakeIWH(texW, texH); |
| + // If the src rectangle contains the whole texture then no need for a domain. |
| + if (constraintRect.contains(textureBounds)) { |
| + return kNoDomain_DomainMode; |
| + } |
| + |
| + bool restrictFilterToRect = (filterConstraint == GrTextureAdjuster::kYes_FilterConstraint); |
| + |
| + // If we can filter outside the constraint rect, and there is no non-content area of the |
| + // texture, and we aren't going to generate sample coords outside the constraint rect then we |
| + // don't need a domain. |
| + if (!restrictFilterToRect && !textureContentArea && coordsLimitedContraintRect) { |
| + return kNoDomain_DomainMode; |
| + } |
| + |
| + // Get the domain inset based on sampling mode (or bail if mipped) |
| + SkScalar filterHalfWidth; |
| + if (filterModeOrNullForBicubic) { |
| + switch (*filterModeOrNullForBicubic) { |
| + case GrTextureParams::kNone_FilterMode: |
| + if (coordsLimitedContraintRect) { |
| + return kNoDomain_DomainMode; |
| + } else { |
| + filterHalfWidth = 0.f; |
| + } |
| + break; |
| + case GrTextureParams::kBilerp_FilterMode: |
| + filterHalfWidth = 1.f; |
| + break; |
| + case GrTextureParams::kMipMap_FilterMode: |
| + // No domain can save use here. |
| + return kTightCopy_DomainMode; |
| + } |
| + } else { |
| + // bicubic does nearest filtering internally. |
| + filterHalfWidth = 2.f; |
| + } |
| + |
|
robertphillips
2015/11/05 20:13:24
// We will inset the domain half a pixel b.c. ...
bsalomon
2015/11/06 15:24:25
Done.
|
| + static const SkScalar kDomainInset = 0.5f; |
|
robertphillips
2015/11/05 20:13:24
can -> to ?
bsalomon
2015/11/06 15:24:26
Done.
|
| + // Figure out the limits of pixels we're allowed can sample from. |
| + // Unless we know the amount of outset and the texture matrix we have to conservatively enforce |
| + // the domain. |
| + if (restrictFilterToRect) { |
| + domainRect->fLeft = constraintRect.fLeft + kDomainInset; |
| + domainRect->fTop = constraintRect.fTop + kDomainInset; |
| + domainRect->fRight = constraintRect.fRight - kDomainInset; |
| + domainRect->fBottom = constraintRect.fBottom - kDomainInset; |
| + } else if (textureContentArea) { |
| + // If we got here then: there is a textureContentArea, the coords are limited to the |
| + // constraint rect, and we're allowed to filter across the constraint rect boundary. So |
|
robertphillips
2015/11/05 20:13:24
from -> to ?
bsalomon
2015/11/06 15:24:26
Done.
|
| + // we check whether the filter would reach from the edge of the content area. |
| + bool needContentAreaConstraint = false; |
| + // We will only set the sides that are required. |
| + domainRect->setLargest(); |
| + if (textureContentArea->fLeft > 0 && |
| + textureContentArea->fLeft + filterHalfWidth > constraintRect.fLeft) { |
| + domainRect->fLeft = textureContentArea->fLeft + kDomainInset; |
| + needContentAreaConstraint = true; |
| + } |
| + if (textureContentArea->fTop > 0 && |
| + textureContentArea->fTop + filterHalfWidth > constraintRect.fTop) { |
| + domainRect->fTop = textureContentArea->fTop + kDomainInset; |
| + needContentAreaConstraint = true; |
| + } |
| + if (textureContentArea->fRight < texW && |
| + textureContentArea->fRight - filterHalfWidth < constraintRect.fRight) { |
| + domainRect->fRight = textureContentArea->fRight - kDomainInset; |
| + needContentAreaConstraint = true; |
| + } |
| + if (textureContentArea->fBottom < texW && |
| + textureContentArea->fBottom - filterHalfWidth < constraintRect.fBottom) { |
| + domainRect->fBottom = textureContentArea->fBottom - kDomainInset; |
| + needContentAreaConstraint = true; |
| + } |
| + if (!needContentAreaConstraint) { |
| + return kNoDomain_DomainMode; |
| + } |
| + } 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); |
| + } |
|
robertphillips
2015/11/05 20:13:24
What happens to the sides that are still out at th
bsalomon
2015/11/06 15:24:26
They'd still be really large (in abs value). This
|
| + domainRect->fLeft /= texW; |
| + domainRect->fTop /= texH; |
| + domainRect->fRight /= texW; |
| + domainRect->fBottom /= texH; |
| + return kDomain_DomainMode; |
| +} |
| + |
| +const GrFragmentProcessor* GrTextureAdjuster::createFragmentProcessor( |
| + const SkMatrix& textureMatrix, |
| + const SkRect& constraintRect, |
| + FilterConstraint filterConstraint, |
| + bool coordsLimitedToConstraintRect, |
| + const GrTextureParams::FilterMode* filterOrNullForBicubic) { |
| + |
| + const SkIRect* contentArea = this->contentArea(); |
| + |
| + SkRect domain; |
| + GrTexture* texture = this->originalTexture(); |
| + DomainMode domainMode = |
| + determine_domain_mode(constraintRect, filterConstraint, coordsLimitedToConstraintRect, |
| + texture->width(), texture->height(), |
| + contentArea, filterOrNullForBicubic, |
| + &domain); |
| + if (kTightCopy_DomainMode == domainMode) { |
| + // TODO: Copy the texture and adjust the texture matrix (both parts need to consider |
| + // non-int constraint rect) |
| + // For now: treat as bilerp and ignore what goes on above level 0. |
| + SkASSERT(filterOrNullForBicubic && |
| + GrTextureParams::kMipMap_FilterMode == *filterOrNullForBicubic); |
| + static const GrTextureParams::FilterMode kBilerp = GrTextureParams::kBilerp_FilterMode; |
| + domainMode = |
| + determine_domain_mode(constraintRect, filterConstraint, coordsLimitedToConstraintRect, |
| + texture->width(), texture->height(), |
| + contentArea, &kBilerp, &domain); |
| + SkASSERT(kTightCopy_DomainMode != domainMode); |
| + filterOrNullForBicubic = &kBilerp; |
| + } |
| + SkASSERT(kNoDomain_DomainMode == domainMode || |
| + (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom)); |
| + if (filterOrNullForBicubic) { |
| + if (kDomain_DomainMode == domainMode) { |
| + SkASSERT(*filterOrNullForBicubic != GrTextureParams::kMipMap_FilterMode); |
| + return GrTextureDomainEffect::Create(texture, textureMatrix, domain, |
| + GrTextureDomain::kClamp_Mode, |
| + *filterOrNullForBicubic); |
| + } else { |
| + GrTextureParams params(SkShader::kClamp_TileMode, *filterOrNullForBicubic); |
| + return GrSimpleTextureEffect::Create(texture, textureMatrix, params); |
| + } |
| + } else { |
| + if (kDomain_DomainMode == domainMode) { |
| + return GrBicubicEffect::Create(texture, textureMatrix, domain); |
| + } else { |
| + static const SkShader::TileMode kClampClamp[] = |
| + { SkShader::kClamp_TileMode, SkShader::kClamp_TileMode }; |
| + return GrBicubicEffect::Create(texture, textureMatrix, kClampClamp); |
| + } |
| + } |
| +} |
| + |
| ////////////////////////////////////////////////////////////////////////////// |
| GrTexture* GrTextureMaker::refTextureForParams(GrContext* ctx, const GrTextureParams& params) { |