From b66b42f1749a7a23fd610d90605978537bf4fbb7 Mon Sep 17 00:00:00 2001 From: Robert Phillips Date: Tue, 14 Mar 2017 08:53:02 -0400 Subject: [PATCH] Preparatory Proxification This is pulled out of: https://skia-review.googlesource.com/c/8823/ (Remove GrFragmentProcessor-derived class' GrTexture-based ctors) Change-Id: I93e233cd80d98c848d79272423cb58505d72ff3e Reviewed-on: https://skia-review.googlesource.com/9559 Reviewed-by: Brian Salomon Commit-Queue: Robert Phillips --- src/core/SkSpecialImage.cpp | 3 +- src/gpu/GrResourceProvider.cpp | 4 ++ src/gpu/GrResourceProvider.h | 4 ++ src/gpu/GrSurfaceProxyPriv.h | 2 +- src/gpu/GrTextureProducer.cpp | 95 +++++++++++++++++++++++++++ src/gpu/GrTextureProducer.h | 13 ++++ src/gpu/effects/GrTextureDomain.cpp | 5 +- src/gpu/ops/GrAADistanceFieldPathRenderer.cpp | 4 +- 8 files changed, 124 insertions(+), 6 deletions(-) diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp index dc71709..331ee66 100644 --- a/src/core/SkSpecialImage.cpp +++ b/src/core/SkSpecialImage.cpp @@ -17,6 +17,7 @@ #if SK_SUPPORT_GPU #include "GrContext.h" +#include "GrResourceProvider.h" #include "GrSurfaceContext.h" #include "GrSurfaceProxyPriv.h" #include "GrTexture.h" @@ -474,7 +475,7 @@ public: if (subset) { // TODO: if this becomes a bottle neck we could base this logic on what the size // will be when it is finally instantiated - but that is more fraught. - if (fTextureProxy->priv().isExact() && + if (GrResourceProvider::IsFunctionallyExact(fTextureProxy.get()) && 0 == subset->fLeft && 0 == subset->fTop && fTextureProxy->width() == subset->width() && fTextureProxy->height() == subset->height()) { diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp index 89c5ed6..2083c7c 100644 --- a/src/gpu/GrResourceProvider.cpp +++ b/src/gpu/GrResourceProvider.cpp @@ -17,6 +17,7 @@ #include "GrResourceKey.h" #include "GrSemaphore.h" #include "GrStencilAttachment.h" +#include "GrSurfaceProxyPriv.h" #include "GrTexturePriv.h" #include "../private/GrSingleOwner.h" #include "SkMathPriv.h" @@ -39,6 +40,9 @@ GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSin fQuadIndexBufferKey = gQuadIndexBufferKey; } +bool GrResourceProvider::IsFunctionallyExact(GrTextureProxy* proxy) { + return proxy->priv().isExact() || (SkIsPow2(proxy->width()) && SkIsPow2(proxy->height())); +} GrTexture* GrResourceProvider::createMipMappedTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted, const GrMipLevel* texels, diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h index 1f1ff8e..bd15b7d 100644 --- a/src/gpu/GrResourceProvider.h +++ b/src/gpu/GrResourceProvider.h @@ -243,6 +243,10 @@ public: fGpu = NULL; } + // 'Proxy' is about to be used as a texture src. This query can be used to determine if + // it is going to need a texture domain. + static bool IsFunctionallyExact(GrTextureProxy* proxy); + private: GrTexture* internalCreateApproxTexture(const GrSurfaceDesc& desc, uint32_t scratchTextureFlags); diff --git a/src/gpu/GrSurfaceProxyPriv.h b/src/gpu/GrSurfaceProxyPriv.h index 390806f..0d10ef6 100644 --- a/src/gpu/GrSurfaceProxyPriv.h +++ b/src/gpu/GrSurfaceProxyPriv.h @@ -20,7 +20,7 @@ public: // future when the proxy is actually used/instantiated. bool hasPendingIO() const { return fProxy->hasPendingIO(); } - // Don't abuse this!!!!!!! + // Don't abuse these two!!!!!!! bool isExact() const { return SkBackingFit::kExact == fProxy->fFit; } // These next two are very specialized and wacky - don't use them! diff --git a/src/gpu/GrTextureProducer.cpp b/src/gpu/GrTextureProducer.cpp index 37fab37..bc16bb5 100644 --- a/src/gpu/GrTextureProducer.cpp +++ b/src/gpu/GrTextureProducer.cpp @@ -8,6 +8,9 @@ #include "GrTextureProducer.h" #include "GrClip.h" #include "GrRenderTargetContext.h" +#include "GrResourceProvider.h" +#include "GrSurfaceProxy.h" +#include "GrSurfaceProxyPriv.h" #include "GrTexture.h" #include "effects/GrBicubicEffect.h" #include "effects/GrSimpleTextureEffect.h" @@ -63,6 +66,64 @@ GrTexture* GrTextureProducer::CopyOnGpu(GrTexture* inputTexture, const SkIRect* return copyRTC->asTexture().release(); } +sk_sp GrTextureProducer::CopyOnGpu(GrContext* context, + sk_sp inputProxy, + const SkIRect* subset, + const CopyParams& copyParams) { + SkASSERT(!subset || !subset->isEmpty()); + SkASSERT(context); + + GrPixelConfig config = GrMakePixelConfigUncompressed(inputProxy->config()); + + const SkRect dstRect = SkRect::MakeIWH(copyParams.fWidth, copyParams.fHeight); + + sk_sp copyRTC = context->makeRenderTargetContextWithFallback( + SkBackingFit::kExact, dstRect.width(), dstRect.height(), config, nullptr); + if (!copyRTC) { + return nullptr; + } + + GrPaint paint; + paint.setGammaCorrect(true); + + SkRect localRect; + if (subset) { + localRect = SkRect::Make(*subset); + } else { + localRect = SkRect::MakeWH(inputProxy->width(), inputProxy->height()); + } + + bool needsDomain = false; + if (copyParams.fFilter != GrSamplerParams::kNone_FilterMode) { + bool resizing = subset->width() != dstRect.width() || subset->height() != dstRect.height(); + + if (GrResourceProvider::IsFunctionallyExact(inputProxy.get())) { + needsDomain = subset && resizing; + } else { + needsDomain = resizing; + } + } + + if (needsDomain) { + const SkRect domain = localRect.makeInset(0.5f, 0.5f); + // 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(context, std::move(inputProxy), nullptr, SkMatrix::I(), + domain, GrTextureDomain::kClamp_Mode, copyParams.fFilter)); + } else { + GrSamplerParams params(SkShader::kClamp_TileMode, copyParams.fFilter); + paint.addColorTextureProcessor(context, std::move(inputProxy), + nullptr, SkMatrix::I(), params); + } + paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + + copyRTC->fillRectToRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect, + localRect); + return copyRTC->asTextureProxyRef(); +} + /** 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 @@ -233,3 +294,37 @@ sk_sp GrTextureProducer::CreateFragmentProcessorForDomainAn } } } + +sk_sp GrTextureProducer::CreateFragmentProcessorForDomainAndFilter( + GrContext* context, + sk_sp proxy, + sk_sp 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(context, std::move(proxy), + std::move(colorSpaceXform), textureMatrix, + domain, GrTextureDomain::kClamp_Mode, + *filterOrNullForBicubic); + } else { + GrSamplerParams params(SkShader::kClamp_TileMode, *filterOrNullForBicubic); + return GrSimpleTextureEffect::Make(context, std::move(proxy), + std::move(colorSpaceXform), textureMatrix, + params); + } + } else { + if (kDomain_DomainMode == domainMode) { + return GrBicubicEffect::Make(context, std::move(proxy), std::move(colorSpaceXform), + textureMatrix, domain); + } else { + static const SkShader::TileMode kClampClamp[] = + { SkShader::kClamp_TileMode, SkShader::kClamp_TileMode }; + return GrBicubicEffect::Make(context, std::move(proxy), std::move(colorSpaceXform), + textureMatrix, kClampClamp); + } + } +} diff --git a/src/gpu/GrTextureProducer.h b/src/gpu/GrTextureProducer.h index 2284cb4..fefdf19 100644 --- a/src/gpu/GrTextureProducer.h +++ b/src/gpu/GrTextureProducer.h @@ -13,6 +13,7 @@ class GrColorSpaceXform; class GrTexture; +class GrTextureProxy; /** * Different GPUs and API extensions have different requirements with respect to what texture @@ -118,6 +119,9 @@ protected: static GrTexture* CopyOnGpu(GrTexture* inputTexture, const SkIRect* subset, const CopyParams& copyParams); + static sk_sp CopyOnGpu(GrContext*, sk_sp inputProxy, + const SkIRect* subset, const CopyParams& copyParams); + static DomainMode DetermineDomainMode( const SkRect& constraintRect, FilterConstraint filterConstraint, @@ -135,6 +139,15 @@ protected: const SkRect& domain, const GrSamplerParams::FilterMode* filterOrNullForBicubic); + static sk_sp CreateFragmentProcessorForDomainAndFilter( + GrContext* context, + sk_sp proxy, + sk_sp colorSpaceXform, + const SkMatrix& textureMatrix, + DomainMode, + const SkRect& domain, + const GrSamplerParams::FilterMode* filterOrNullForBicubic); + private: const int fWidth; const int fHeight; diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp index 7a43328..7bd41a7 100644 --- a/src/gpu/effects/GrTextureDomain.cpp +++ b/src/gpu/effects/GrTextureDomain.cpp @@ -8,6 +8,7 @@ #include "GrTextureDomain.h" #include "GrContext.h" +#include "GrResourceProvider.h" #include "GrShaderCaps.h" #include "GrSimpleTextureEffect.h" #include "GrSurfaceProxyPriv.h" @@ -19,8 +20,8 @@ #include "glsl/GrGLSLShaderBuilder.h" #include "glsl/GrGLSLUniformHandler.h" -static bool can_ignore_rect(GrSurfaceProxy* proxy, const SkRect& domain) { - if (proxy->priv().isExact()) { +static bool can_ignore_rect(GrTextureProxy* proxy, const SkRect& domain) { + if (GrResourceProvider::IsFunctionallyExact(proxy)) { const SkIRect kFullRect = SkIRect::MakeWH(proxy->width(), proxy->height()); return domain.contains(kFullRect); diff --git a/src/gpu/ops/GrAADistanceFieldPathRenderer.cpp b/src/gpu/ops/GrAADistanceFieldPathRenderer.cpp index e77dfa9..74eda37 100644 --- a/src/gpu/ops/GrAADistanceFieldPathRenderer.cpp +++ b/src/gpu/ops/GrAADistanceFieldPathRenderer.cpp @@ -646,8 +646,8 @@ private: // convert texcoords to unsigned short format sk_sp proxy = atlas->getProxy(); - // The proxy must be exact for this normalization to work correctly - SkASSERT(proxy->priv().isExact()); + // The proxy must be functionally exact for this normalization to work correctly + SkASSERT(GrResourceProvider::IsFunctionallyExact(proxy.get())); SkScalar uFactor = 65535.f / proxy->width(); SkScalar vFactor = 65535.f / proxy->height(); uint16_t l = (uint16_t)(texLeft*uFactor); -- 2.7.4