aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/SkSpecialImage.cpp3
-rw-r--r--src/gpu/GrResourceProvider.cpp4
-rw-r--r--src/gpu/GrResourceProvider.h4
-rw-r--r--src/gpu/GrSurfaceProxyPriv.h2
-rw-r--r--src/gpu/GrTextureProducer.cpp95
-rw-r--r--src/gpu/GrTextureProducer.h13
-rw-r--r--src/gpu/effects/GrTextureDomain.cpp5
-rw-r--r--src/gpu/ops/GrAADistanceFieldPathRenderer.cpp4
8 files changed, 124 insertions, 6 deletions
diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp
index dc717095a8..331ee66fb6 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 89c5ed6945..2083c7c72b 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 1f1ff8e173..bd15b7dca9 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 390806f0c0..0d10ef6504 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 37fab37737..bc16bb5fcf 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<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);
+ }
+ }
+}
diff --git a/src/gpu/GrTextureProducer.h b/src/gpu/GrTextureProducer.h
index 2284cb4c05..fefdf1969f 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<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;
diff --git a/src/gpu/effects/GrTextureDomain.cpp b/src/gpu/effects/GrTextureDomain.cpp
index 7a43328bc1..7bd41a7be4 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 e77dfa9068..74eda37a04 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<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);