aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrTextureParamsAdjuster.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/GrTextureParamsAdjuster.cpp')
-rw-r--r--src/gpu/GrTextureParamsAdjuster.cpp524
1 files changed, 0 insertions, 524 deletions
diff --git a/src/gpu/GrTextureParamsAdjuster.cpp b/src/gpu/GrTextureParamsAdjuster.cpp
deleted file mode 100644
index d924f4a976..0000000000
--- a/src/gpu/GrTextureParamsAdjuster.cpp
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrTextureParamsAdjuster.h"
-
-#include "GrCaps.h"
-#include "GrColorSpaceXform.h"
-#include "GrContext.h"
-#include "GrRenderTargetContext.h"
-#include "GrGpu.h"
-#include "GrGpuResourcePriv.h"
-#include "GrResourceKey.h"
-#include "GrTexture.h"
-#include "GrSamplerParams.h"
-#include "GrTextureProvider.h"
-#include "SkCanvas.h"
-#include "SkGr.h"
-#include "SkGrPriv.h"
-#include "effects/GrBicubicEffect.h"
-#include "effects/GrSimpleTextureEffect.h"
-#include "effects/GrTextureDomain.h"
-
-typedef GrTextureProducer::CopyParams CopyParams;
-
-//////////////////////////////////////////////////////////////////////////////
-
-static GrTexture* copy_on_gpu(GrTexture* inputTexture, const SkIRect* subset,
- const CopyParams& copyParams) {
- SkASSERT(!subset || !subset->isEmpty());
- GrContext* context = inputTexture->getContext();
- SkASSERT(context);
-
- GrPixelConfig config = GrMakePixelConfigUncompressed(inputTexture->config());
-
- sk_sp<GrRenderTargetContext> copyRTC = context->makeRenderTargetContextWithFallback(
- SkBackingFit::kExact, copyParams.fWidth, copyParams.fHeight, config, nullptr);
- if (!copyRTC) {
- return nullptr;
- }
-
- GrPaint paint;
- paint.setGammaCorrect(true);
-
- SkScalar sx SK_INIT_TO_AVOID_WARNING;
- SkScalar sy SK_INIT_TO_AVOID_WARNING;
- if (subset) {
- sx = 1.f / inputTexture->width();
- sy = 1.f / inputTexture->height();
- }
-
- if (copyParams.fFilter != GrSamplerParams::kNone_FilterMode && subset &&
- (subset->width() != copyParams.fWidth || subset->height() != copyParams.fHeight)) {
- SkRect domain;
- domain.fLeft = (subset->fLeft + 0.5f) * sx;
- domain.fTop = (subset->fTop + 0.5f)* sy;
- domain.fRight = (subset->fRight - 0.5f) * sx;
- domain.fBottom = (subset->fBottom - 0.5f) * sy;
- // This would cause us to read values from outside the subset. Surely, the caller knows
- // better!
- SkASSERT(copyParams.fFilter != GrSamplerParams::kMipMap_FilterMode);
- paint.addColorFragmentProcessor(
- GrTextureDomainEffect::Make(inputTexture, nullptr, SkMatrix::I(), domain,
- GrTextureDomain::kClamp_Mode,
- copyParams.fFilter));
- } else {
- GrSamplerParams params(SkShader::kClamp_TileMode, copyParams.fFilter);
- paint.addColorTextureProcessor(inputTexture, nullptr, SkMatrix::I(), params);
- }
- paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
-
- SkRect localRect;
- if (subset) {
- localRect = SkRect::Make(*subset);
- localRect.fLeft *= sx;
- localRect.fTop *= sy;
- localRect.fRight *= sx;
- localRect.fBottom *= sy;
- } else {
- localRect = SkRect::MakeWH(1.f, 1.f);
- }
-
- SkRect dstRect = SkRect::MakeIWH(copyParams.fWidth, copyParams.fHeight);
- copyRTC->fillRectToRect(GrNoClip(), paint, SkMatrix::I(), dstRect, localRect);
- return copyRTC->asTexture().release();
-}
-
-GrTextureAdjuster::GrTextureAdjuster(GrTexture* original, SkAlphaType alphaType,
- const SkIRect& contentArea, uint32_t uniqueID,
- SkColorSpace* cs)
- : INHERITED(contentArea.width(), contentArea.height(),
- GrPixelConfigIsAlphaOnly(original->config()))
- , fOriginal(original)
- , fAlphaType(alphaType)
- , fColorSpace(cs)
- , fUniqueID(uniqueID)
-{
- SkASSERT(SkIRect::MakeWH(original->width(), original->height()).contains(contentArea));
- if (contentArea.fLeft > 0 || contentArea.fTop > 0 ||
- contentArea.fRight < original->width() || contentArea.fBottom < original->height()) {
- fContentArea.set(contentArea);
- }
-}
-
-void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey,
- SkDestinationSurfaceColorMode) {
- // Color mode is irrelevant in this case - we already have a texture so we're just sub-setting
- GrUniqueKey baseKey;
- GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeWH(this->width(), this->height()));
- MakeCopyKeyFromOrigKey(baseKey, params, copyKey);
-}
-
-void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey) {
- // We don't currently have a mechanism for notifications on Images!
-}
-
-GrTexture* GrTextureAdjuster::refCopy(const CopyParams& copyParams) {
- GrTexture* texture = this->originalTexture();
- GrContext* context = texture->getContext();
- const SkIRect* contentArea = this->contentAreaOrNull();
- GrUniqueKey key;
- this->makeCopyKey(copyParams, &key, SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware);
- if (key.isValid()) {
- GrTexture* cachedCopy = context->textureProvider()->findAndRefTextureByUniqueKey(key);
- if (cachedCopy) {
- return cachedCopy;
- }
- }
- GrTexture* copy = copy_on_gpu(texture, contentArea, copyParams);
- if (copy) {
- if (key.isValid()) {
- copy->resourcePriv().setUniqueKey(key);
- this->didCacheCopy(key);
- }
- }
- return copy;
-}
-
-GrTexture* GrTextureAdjuster::refTextureSafeForParams(const GrSamplerParams& params,
- SkDestinationSurfaceColorMode colorMode,
- SkIPoint* outOffset) {
- GrTexture* texture = this->originalTexture();
- GrContext* context = texture->getContext();
- CopyParams copyParams;
- const SkIRect* contentArea = this->contentAreaOrNull();
-
- if (!context) {
- // The texture was abandoned.
- return nullptr;
- }
-
- if (contentArea && GrSamplerParams::kMipMap_FilterMode == params.filterMode()) {
- // If we generate a MIP chain for texture it will read pixel values from outside the content
- // area.
- copyParams.fWidth = contentArea->width();
- copyParams.fHeight = contentArea->height();
- copyParams.fFilter = GrSamplerParams::kBilerp_FilterMode;
- } else if (!context->getGpu()->makeCopyForTextureParams(texture, params, &copyParams)) {
- if (outOffset) {
- if (contentArea) {
- outOffset->set(contentArea->fLeft, contentArea->fRight);
- } else {
- outOffset->set(0, 0);
- }
- }
- return SkRef(texture);
- }
-
- GrTexture* copy = this->refCopy(copyParams);
- if (copy && outOffset) {
- outOffset->set(0, 0);
- }
- return copy;
-}
-
-enum DomainMode {
- kNoDomain_DomainMode,
- kDomain_DomainMode,
- kTightCopy_DomainMode
-};
-
-/** Determines whether a texture domain is necessary and if so what domain to use. There are two
- * rectangles to consider:
- * - The first is the content area specified by the texture adjuster. We can *never* allow
- * filtering to cause bleed of pixels outside this rectangle.
- * - The second rectangle is the constraint rectangle, which is known to be contained by the
- * content area. The filterConstraint specifies whether we are allowed to bleed across this
- * rect.
- *
- * We want to avoid using a domain if possible. We consider the above rectangles, the filter type,
- * and whether the coords generated by the draw would all fall within the constraint rect. If the
- * latter is true we only need to consider whether the filter would extend beyond the rects.
- */
-static DomainMode determine_domain_mode(
- const SkRect& constraintRect,
- GrTextureAdjuster::FilterConstraint filterConstraint,
- bool coordsLimitedToConstraintRect,
- int texW, int texH,
- const SkIRect* textureContentArea,
- const GrSamplerParams::FilterMode* filterModeOrNullForBicubic,
- SkRect* domainRect) {
-
- 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 == GrTextureProducer::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 && 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 || textureContentArea) {
- // 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->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
- // 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 (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 < texH &&
- textureContentArea->fBottom - filterHalfWidth < constraintRect.fBottom) {
- domainRect->fBottom = textureContentArea->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 (textureContentArea->fLeft != 0) {
- domainRect->fLeft = textureContentArea->fLeft + kDomainInset;
- }
- if (textureContentArea->fTop != 0) {
- domainRect->fTop = textureContentArea->fTop + kDomainInset;
- }
- if (textureContentArea->fRight != texW) {
- domainRect->fRight = textureContentArea->fRight - kDomainInset;
- }
- if (textureContentArea->fBottom != texH) {
- domainRect->fBottom = textureContentArea->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);
- }
- domainRect->fLeft /= texW;
- domainRect->fTop /= texH;
- domainRect->fRight /= texW;
- domainRect->fBottom /= texH;
- return kDomain_DomainMode;
-}
-
-static sk_sp<GrFragmentProcessor> create_fp_for_domain_and_filter(
- GrTexture* texture,
- sk_sp<GrColorSpaceXform> colorSpaceXform,
- const SkMatrix& textureMatrix,
- DomainMode domainMode,
- const SkRect& domain,
- const GrSamplerParams::FilterMode* filterOrNullForBicubic) {
- SkASSERT(kTightCopy_DomainMode != domainMode);
- if (filterOrNullForBicubic) {
- if (kDomain_DomainMode == domainMode) {
- return GrTextureDomainEffect::Make(texture, std::move(colorSpaceXform), textureMatrix,
- domain, GrTextureDomain::kClamp_Mode,
- *filterOrNullForBicubic);
- } else {
- GrSamplerParams params(SkShader::kClamp_TileMode, *filterOrNullForBicubic);
- return GrSimpleTextureEffect::Make(texture, std::move(colorSpaceXform), textureMatrix,
- params);
- }
- } else {
- if (kDomain_DomainMode == domainMode) {
- return GrBicubicEffect::Make(texture, std::move(colorSpaceXform), textureMatrix,
- domain);
- } else {
- static const SkShader::TileMode kClampClamp[] =
- { SkShader::kClamp_TileMode, SkShader::kClamp_TileMode };
- return GrBicubicEffect::Make(texture, std::move(colorSpaceXform), textureMatrix,
- kClampClamp);
- }
- }
-}
-
-sk_sp<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
- const SkMatrix& origTextureMatrix,
- const SkRect& origConstraintRect,
- FilterConstraint filterConstraint,
- bool coordsLimitedToConstraintRect,
- const GrSamplerParams::FilterMode* filterOrNullForBicubic,
- SkColorSpace* dstColorSpace,
- SkDestinationSurfaceColorMode colorMode) {
-
- SkMatrix textureMatrix = origTextureMatrix;
- const SkIRect* contentArea = this->contentAreaOrNull();
- // Convert the constraintRect to be relative to the texture rather than the content area so
- // that both rects are in the same coordinate system.
- SkTCopyOnFirstWrite<SkRect> constraintRect(origConstraintRect);
- if (contentArea) {
- SkScalar l = SkIntToScalar(contentArea->fLeft);
- SkScalar t = SkIntToScalar(contentArea->fTop);
- constraintRect.writable()->offset(l, t);
- textureMatrix.postTranslate(l, t);
- }
-
- SkRect domain;
- GrSamplerParams params;
- if (filterOrNullForBicubic) {
- params.setFilterMode(*filterOrNullForBicubic);
- }
- sk_sp<GrTexture> texture(this->refTextureSafeForParams(params, colorMode, nullptr));
- if (!texture) {
- return nullptr;
- }
- // If we made a copy then we only copied the contentArea, in which case the new texture is all
- // content.
- if (texture.get() != this->originalTexture()) {
- contentArea = nullptr;
- }
-
- 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.
-
- // We only expect MIP maps to require a tight copy.
- SkASSERT(filterOrNullForBicubic &&
- GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic);
- static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode;
- domainMode =
- determine_domain_mode(*constraintRect, filterConstraint, coordsLimitedToConstraintRect,
- texture->width(), texture->height(),
- contentArea, &kBilerp, &domain);
- SkASSERT(kTightCopy_DomainMode != domainMode);
- }
- SkASSERT(kNoDomain_DomainMode == domainMode ||
- (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
- textureMatrix.postIDiv(texture->width(), texture->height());
- sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace,
- dstColorSpace);
- return create_fp_for_domain_and_filter(texture.get(), std::move(colorSpaceXform), textureMatrix,
- domainMode, domain, filterOrNullForBicubic);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-GrTexture* GrTextureMaker::refTextureForParams(const GrSamplerParams& params,
- SkDestinationSurfaceColorMode colorMode,
- sk_sp<SkColorSpace>* texColorSpace) {
- CopyParams copyParams;
- bool willBeMipped = params.filterMode() == GrSamplerParams::kMipMap_FilterMode;
-
- if (!fContext->caps()->mipMapSupport()) {
- willBeMipped = false;
- }
-
- if (texColorSpace) {
- *texColorSpace = this->getColorSpace(colorMode);
- }
-
- if (!fContext->getGpu()->makeCopyForTextureParams(this->width(), this->height(), params,
- &copyParams)) {
- return this->refOriginalTexture(willBeMipped, colorMode);
- }
- GrUniqueKey copyKey;
- this->makeCopyKey(copyParams, &copyKey, colorMode);
- if (copyKey.isValid()) {
- GrTexture* result = fContext->textureProvider()->findAndRefTextureByUniqueKey(copyKey);
- if (result) {
- return result;
- }
- }
-
- GrTexture* result = this->generateTextureForParams(copyParams, willBeMipped, colorMode);
- if (!result) {
- return nullptr;
- }
-
- if (copyKey.isValid()) {
- fContext->textureProvider()->assignUniqueKeyToTexture(copyKey, result);
- this->didCacheCopy(copyKey);
- }
- return result;
-}
-
-sk_sp<GrFragmentProcessor> GrTextureMaker::createFragmentProcessor(
- const SkMatrix& textureMatrix,
- const SkRect& constraintRect,
- FilterConstraint filterConstraint,
- bool coordsLimitedToConstraintRect,
- const GrSamplerParams::FilterMode* filterOrNullForBicubic,
- SkColorSpace* dstColorSpace,
- SkDestinationSurfaceColorMode colorMode) {
-
- const GrSamplerParams::FilterMode* fmForDetermineDomain = filterOrNullForBicubic;
- if (filterOrNullForBicubic && GrSamplerParams::kMipMap_FilterMode == *filterOrNullForBicubic &&
- kYes_FilterConstraint == filterConstraint) {
- // TODo: Here we should force a copy restricted to the constraintRect since MIP maps will
- // read outside the constraint rect. However, as in the adjuster case, we aren't currently
- // doing that.
- // We instead we compute the domain as though were bilerping which is only correct if we
- // only sample level 0.
- static const GrSamplerParams::FilterMode kBilerp = GrSamplerParams::kBilerp_FilterMode;
- fmForDetermineDomain = &kBilerp;
- }
-
- GrSamplerParams params;
- if (filterOrNullForBicubic) {
- params.reset(SkShader::kClamp_TileMode, *filterOrNullForBicubic);
- } else {
- // Bicubic doesn't use filtering for it's texture accesses.
- params.reset(SkShader::kClamp_TileMode, GrSamplerParams::kNone_FilterMode);
- }
- sk_sp<SkColorSpace> texColorSpace;
- sk_sp<GrTexture> texture(this->refTextureForParams(params, colorMode, &texColorSpace));
- if (!texture) {
- return nullptr;
- }
- SkRect domain;
- DomainMode domainMode =
- determine_domain_mode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
- texture->width(), texture->height(), nullptr, fmForDetermineDomain,
- &domain);
- SkASSERT(kTightCopy_DomainMode != domainMode);
- SkMatrix normalizedTextureMatrix = textureMatrix;
- normalizedTextureMatrix.postIDiv(texture->width(), texture->height());
- sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(texColorSpace.get(),
- dstColorSpace);
- return create_fp_for_domain_and_filter(texture.get(), std::move(colorSpaceXform),
- normalizedTextureMatrix, domainMode, domain,
- filterOrNullForBicubic);
-}
-
-GrTexture* GrTextureMaker::generateTextureForParams(const CopyParams& copyParams, bool willBeMipped,
- SkDestinationSurfaceColorMode colorMode) {
- sk_sp<GrTexture> original(this->refOriginalTexture(willBeMipped, colorMode));
- if (!original) {
- return nullptr;
- }
- return copy_on_gpu(original.get(), nullptr, copyParams);
-}