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 <bsalomon@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2017-03-14 08:53:02 -04:00 committed by Skia Commit-Bot
parent f85f2a9c93
commit b66b42f174
8 changed files with 124 additions and 6 deletions

View File

@ -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()) {

View File

@ -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,

View File

@ -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);

View File

@ -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!

View File

@ -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<GrTextureProxy> GrTextureProducer::CopyOnGpu(GrContext* context,
sk_sp<GrTextureProxy> 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<GrRenderTargetContext> 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<GrFragmentProcessor> GrTextureProducer::CreateFragmentProcessorForDomainAn
}
}
}
sk_sp<GrFragmentProcessor> GrTextureProducer::CreateFragmentProcessorForDomainAndFilter(
GrContext* context,
sk_sp<GrTextureProxy> proxy,
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(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);
}
}
}

View File

@ -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<GrTextureProxy> CopyOnGpu(GrContext*, sk_sp<GrTextureProxy> 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<GrFragmentProcessor> CreateFragmentProcessorForDomainAndFilter(
GrContext* context,
sk_sp<GrTextureProxy> proxy,
sk_sp<GrColorSpaceXform> colorSpaceXform,
const SkMatrix& textureMatrix,
DomainMode,
const SkRect& domain,
const GrSamplerParams::FilterMode* filterOrNullForBicubic);
private:
const int fWidth;
const int fHeight;

View File

@ -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);

View File

@ -646,8 +646,8 @@ private:
// convert texcoords to unsigned short format
sk_sp<GrTextureProxy> 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);