Make blur utils take GrTextureProxies - take 2
This is a re-land of https://skia-review.googlesource.com/c/7738/ (Make blur utils take GrTextureProxies) with a fix for the Nexus7
Change-Id: I5821a26b1e986daa11d960ae826a1207512cd2a0
Reviewed-on: https://skia-review.googlesource.com/7746
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/core/SkBlurImageFilter.cpp b/src/core/SkBlurImageFilter.cpp
index 6f7a2e3..1a0515b 100644
--- a/src/core/SkBlurImageFilter.cpp
+++ b/src/core/SkBlurImageFilter.cpp
@@ -141,7 +141,7 @@
// xform during the filter itself.
input = ImageToColorSpace(input.get(), ctx.outputProperties());
- sk_sp<GrTexture> inputTexture(input->asTextureRef(context));
+ sk_sp<GrTextureProxy> inputTexture(input->asTextureProxy(context));
if (!inputTexture) {
return nullptr;
}
@@ -163,7 +163,7 @@
// have the same gamut, so in this case, we do everything in the input's color space.
sk_sp<GrRenderTargetContext> renderTargetContext(SkGpuBlurUtils::GaussianBlur(
context,
- inputTexture.get(),
+ std::move(inputTexture),
sk_ref_sp(input->getColorSpace()),
dstBounds,
&inputBounds,
diff --git a/src/core/SkGpuBlurUtils.cpp b/src/core/SkGpuBlurUtils.cpp
index d7522ca..d58582d 100644
--- a/src/core/SkGpuBlurUtils.cpp
+++ b/src/core/SkGpuBlurUtils.cpp
@@ -66,20 +66,21 @@
return sigma;
}
-static void convolve_gaussian_1d(GrRenderTargetContext* renderTargetContext,
+static void convolve_gaussian_1d(GrContext* context,
+ GrRenderTargetContext* renderTargetContext,
const GrClip& clip,
const SkIRect& dstRect,
const SkIPoint& srcOffset,
- GrTexture* texture,
+ sk_sp<GrTextureProxy> proxy,
Gr1DKernelEffect::Direction direction,
int radius,
float sigma,
bool useBounds,
- float bounds[2]) {
+ int bounds[2]) {
GrPaint paint;
paint.setGammaCorrect(renderTargetContext->isGammaCorrect());
sk_sp<GrFragmentProcessor> conv(GrGaussianConvolutionFragmentProcessor::Make(
- texture, direction, radius, sigma, useBounds, bounds));
+ context, std::move(proxy), direction, radius, sigma, useBounds, bounds));
paint.addColorFragmentProcessor(std::move(conv));
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
SkMatrix localMatrix = SkMatrix::MakeTrans(-SkIntToScalar(srcOffset.x()),
@@ -88,11 +89,12 @@
SkRect::Make(dstRect), localMatrix);
}
-static void convolve_gaussian_2d(GrRenderTargetContext* renderTargetContext,
+static void convolve_gaussian_2d(GrContext* context,
+ GrRenderTargetContext* renderTargetContext,
const GrClip& clip,
const SkIRect& dstRect,
const SkIPoint& srcOffset,
- GrTexture* texture,
+ sk_sp<GrTextureProxy> proxy,
int radiusX,
int radiusY,
SkScalar sigmaX,
@@ -107,7 +109,7 @@
SkIRect bounds = srcBounds ? *srcBounds : SkIRect::EmptyIRect();
sk_sp<GrFragmentProcessor> conv(GrMatrixConvolutionEffect::MakeGaussian(
- texture, bounds, size, 1.0, 0.0, kernelOffset,
+ context, std::move(proxy), bounds, size, 1.0, 0.0, kernelOffset,
srcBounds ? GrTextureDomain::kDecal_Mode : GrTextureDomain::kIgnore_Mode,
true, sigmaX, sigmaY));
paint.addColorFragmentProcessor(std::move(conv));
@@ -116,28 +118,29 @@
SkRect::Make(dstRect), localMatrix);
}
-static void convolve_gaussian(GrRenderTargetContext* renderTargetContext,
+static void convolve_gaussian(GrContext* context,
+ GrRenderTargetContext* renderTargetContext,
const GrClip& clip,
const SkIRect& srcRect,
- GrTexture* texture,
+ sk_sp<GrTextureProxy> proxy,
Gr1DKernelEffect::Direction direction,
int radius,
float sigma,
const SkIRect* srcBounds,
const SkIPoint& srcOffset) {
- float bounds[2] = { 0.0f, 1.0f };
+ int bounds[2] = { 0, 0 };
SkIRect dstRect = SkIRect::MakeWH(srcRect.width(), srcRect.height());
if (!srcBounds) {
- convolve_gaussian_1d(renderTargetContext, clip, dstRect, srcOffset, texture,
- direction, radius, sigma, false, bounds);
+ convolve_gaussian_1d(context, renderTargetContext, clip, dstRect, srcOffset,
+ std::move(proxy), direction, radius, sigma, false, bounds);
return;
}
SkIRect midRect = *srcBounds, leftRect, rightRect;
midRect.offset(srcOffset);
SkIRect topRect, bottomRect;
if (direction == Gr1DKernelEffect::kX_Direction) {
- bounds[0] = SkIntToFloat(srcBounds->left()) / texture->width();
- bounds[1] = SkIntToFloat(srcBounds->right()) / texture->width();
+ bounds[0] = srcBounds->left();
+ bounds[1] = srcBounds->right();
topRect = SkIRect::MakeLTRB(0, 0, dstRect.right(), midRect.top());
bottomRect = SkIRect::MakeLTRB(0, midRect.bottom(), dstRect.right(), dstRect.bottom());
midRect.inset(radius, 0);
@@ -147,8 +150,8 @@
dstRect.fTop = midRect.top();
dstRect.fBottom = midRect.bottom();
} else {
- bounds[0] = SkIntToFloat(srcBounds->top()) / texture->height();
- bounds[1] = SkIntToFloat(srcBounds->bottom()) / texture->height();
+ bounds[0] = srcBounds->top();
+ bounds[1] = srcBounds->bottom();
topRect = SkIRect::MakeLTRB(0, 0, midRect.left(), dstRect.bottom());
bottomRect = SkIRect::MakeLTRB(midRect.right(), 0, dstRect.right(), dstRect.bottom());
midRect.inset(0, radius);
@@ -167,23 +170,23 @@
}
if (midRect.isEmpty()) {
// Blur radius covers srcBounds; use bounds over entire draw
- convolve_gaussian_1d(renderTargetContext, clip, dstRect, srcOffset, texture,
- direction, radius, sigma, true, bounds);
+ convolve_gaussian_1d(context, renderTargetContext, clip, dstRect, srcOffset,
+ std::move(proxy), direction, radius, sigma, true, bounds);
} else {
// Draw right and left margins with bounds; middle without.
- convolve_gaussian_1d(renderTargetContext, clip, leftRect, srcOffset, texture,
- direction, radius, sigma, true, bounds);
- convolve_gaussian_1d(renderTargetContext, clip, rightRect, srcOffset, texture,
- direction, radius, sigma, true, bounds);
- convolve_gaussian_1d(renderTargetContext, clip, midRect, srcOffset, texture,
- direction, radius, sigma, false, bounds);
+ convolve_gaussian_1d(context, renderTargetContext, clip, leftRect, srcOffset,
+ proxy, direction, radius, sigma, true, bounds);
+ convolve_gaussian_1d(context, renderTargetContext, clip, rightRect, srcOffset,
+ proxy, direction, radius, sigma, true, bounds);
+ convolve_gaussian_1d(context, renderTargetContext, clip, midRect, srcOffset,
+ std::move(proxy), direction, radius, sigma, false, bounds);
}
}
namespace SkGpuBlurUtils {
sk_sp<GrRenderTargetContext> GaussianBlur(GrContext* context,
- GrTexture* origSrc,
+ sk_sp<GrTextureProxy> srcProxy,
sk_sp<SkColorSpace> colorSpace,
const SkIRect& dstBounds,
const SkIRect* srcBounds,
@@ -217,18 +220,14 @@
// setup new clip
GrFixedClip clip(localDstBounds);
- sk_sp<GrTexture> srcTexture(sk_ref_sp(origSrc));
+ const GrPixelConfig config = srcProxy->config();
- SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
- kRGBA_8888_GrPixelConfig == srcTexture->config() ||
- kSRGBA_8888_GrPixelConfig == srcTexture->config() ||
- kSBGRA_8888_GrPixelConfig == srcTexture->config() ||
- kRGBA_half_GrPixelConfig == srcTexture->config() ||
- kAlpha_8_GrPixelConfig == srcTexture->config());
+ SkASSERT(kBGRA_8888_GrPixelConfig == config || kRGBA_8888_GrPixelConfig == config ||
+ kSRGBA_8888_GrPixelConfig == config || kSBGRA_8888_GrPixelConfig == config ||
+ kRGBA_half_GrPixelConfig == config || kAlpha_8_GrPixelConfig == config);
const int width = dstBounds.width();
const int height = dstBounds.height();
- const GrPixelConfig config = srcTexture->config();
sk_sp<GrRenderTargetContext> dstRenderTargetContext(context->makeDeferredRenderTargetContext(
fit, width, height, config, colorSpace, 0, kBottomLeft_GrSurfaceOrigin));
@@ -243,8 +242,8 @@
// We shouldn't be scaling because this is a small size blur
SkASSERT((1 == scaleFactorX) && (1 == scaleFactorY));
- convolve_gaussian_2d(dstRenderTargetContext.get(), clip, localDstBounds, srcOffset,
- srcTexture.get(), radiusX, radiusY, sigmaX, sigmaY, srcBounds);
+ convolve_gaussian_2d(context, dstRenderTargetContext.get(), clip, localDstBounds, srcOffset,
+ std::move(srcProxy), radiusX, radiusY, sigmaX, sigmaY, srcBounds);
return dstRenderTargetContext;
}
@@ -268,7 +267,8 @@
domain.inset((i < scaleFactorX) ? SK_ScalarHalf : 0.0f,
(i < scaleFactorY) ? SK_ScalarHalf : 0.0f);
sk_sp<GrFragmentProcessor> fp(GrTextureDomainEffect::Make(
- srcTexture.get(),
+ context,
+ std::move(srcProxy),
nullptr,
SkMatrix::I(),
domain,
@@ -279,7 +279,8 @@
srcOffset.set(0, 0);
} else {
GrSamplerParams params(SkShader::kClamp_TileMode, GrSamplerParams::kBilerp_FilterMode);
- paint.addColorTextureProcessor(srcTexture.get(), nullptr, SkMatrix::I(), params);
+ paint.addColorTextureProcessor(context, std::move(srcProxy), nullptr,
+ SkMatrix::I(), params);
}
paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
shrink_irect_by_2(&dstRect, i < scaleFactorX, i < scaleFactorY);
@@ -289,8 +290,8 @@
srcRenderTargetContext = dstRenderTargetContext;
srcRect = dstRect;
- srcTexture = srcRenderTargetContext->asTexture();
- if (!srcTexture) {
+ srcProxy = sk_ref_sp(srcRenderTargetContext->asDeferredTexture());
+ if (!srcProxy) {
return nullptr;
}
dstRenderTargetContext.swap(tmpRenderTargetContext);
@@ -310,12 +311,12 @@
srcRenderTargetContext->priv().absClear(&clearRect, 0x0);
}
- convolve_gaussian(dstRenderTargetContext.get(), clip, srcRect,
- srcTexture.get(), Gr1DKernelEffect::kX_Direction, radiusX, sigmaX,
+ convolve_gaussian(context, dstRenderTargetContext.get(), clip, srcRect,
+ std::move(srcProxy), Gr1DKernelEffect::kX_Direction, radiusX, sigmaX,
srcBounds, srcOffset);
srcRenderTargetContext = dstRenderTargetContext;
- srcTexture = srcRenderTargetContext->asTexture();
- if (!srcTexture) {
+ srcProxy = sk_ref_sp(srcRenderTargetContext->asDeferredTexture());
+ if (!srcProxy) {
return nullptr;
}
srcRect.offsetTo(0, 0);
@@ -335,8 +336,8 @@
srcRenderTargetContext->priv().absClear(&clearRect, 0x0);
}
- convolve_gaussian(dstRenderTargetContext.get(), clip, srcRect,
- srcTexture.get(), Gr1DKernelEffect::kY_Direction, radiusY, sigmaY,
+ convolve_gaussian(context, dstRenderTargetContext.get(), clip, srcRect,
+ std::move(srcProxy), Gr1DKernelEffect::kY_Direction, radiusY, sigmaY,
srcBounds, srcOffset);
srcRenderTargetContext = dstRenderTargetContext;
@@ -345,7 +346,7 @@
}
SkASSERT(srcRenderTargetContext);
- srcTexture = nullptr; // we don't use this from here on out
+ srcProxy.reset(nullptr); // we don't use this from here on out
if (scaleFactorX > 1 || scaleFactorY > 1) {
// Clear one pixel to the right and below, to accommodate bilinear upsampling.
diff --git a/src/core/SkGpuBlurUtils.h b/src/core/SkGpuBlurUtils.h
index 7849e8c..c6c56b6 100644
--- a/src/core/SkGpuBlurUtils.h
+++ b/src/core/SkGpuBlurUtils.h
@@ -22,7 +22,7 @@
* as a renderTargetContext in case the caller wishes to future draw into the result.
* Note: one of sigmaX and sigmaY should be non-zero!
* @param context The GPU context
- * @param srcTexture The source texture to be blurred.
+ * @param src The source to be blurred.
* @param colorSpace Color space of the source (used for the renderTargetContext result,
* too).
* @param dstBounds The destination bounds, relative to the source texture.
@@ -34,7 +34,7 @@
* @return The renderTargetContext containing the blurred result.
*/
sk_sp<GrRenderTargetContext> GaussianBlur(GrContext* context,
- GrTexture* srcTexture,
+ sk_sp<GrTextureProxy> src,
sk_sp<SkColorSpace> colorSpace,
const SkIRect& dstBounds,
const SkIRect* srcBounds,
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index bf54407..594a94e 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -1135,12 +1135,12 @@
rtc->drawRRect(GrNoClip(), std::move(paint), GrAA::kYes, SkMatrix::I(), rrectToDraw,
GrStyle::SimpleFill());
- sk_sp<GrTexture> srcTexture(rtc->asTexture());
- if (!srcTexture) {
+ sk_sp<GrTextureProxy> srcProxy(sk_ref_sp(rtc->asDeferredTexture()));
+ if (!srcProxy) {
return nullptr;
}
sk_sp<GrRenderTargetContext> rtc2(SkGpuBlurUtils::GaussianBlur(context,
- srcTexture.get(),
+ std::move(srcProxy),
nullptr,
SkIRect::MakeWH(
size.fWidth,
@@ -1498,16 +1498,11 @@
SkScalar xformedSigma = this->computeXformedSigma(ctm);
SkASSERT(xformedSigma > 0);
- // TODO: defer this further (i.e., push the proxy into GaussianBlur)
- GrTexture* src = srcProxy->instantiate(context->textureProvider());
- if (!src) {
- return nullptr;
- }
-
// If we're doing a normal blur, we can clobber the pathTexture in the
// gaussianBlur. Otherwise, we need to save it for later compositing.
bool isNormalBlur = (kNormal_SkBlurStyle == fBlurStyle);
- sk_sp<GrRenderTargetContext> renderTargetContext(SkGpuBlurUtils::GaussianBlur(context, src,
+ sk_sp<GrRenderTargetContext> renderTargetContext(SkGpuBlurUtils::GaussianBlur(context,
+ srcProxy,
nullptr, clipRect,
nullptr,
xformedSigma,
@@ -1520,7 +1515,7 @@
GrPaint paint;
// Blend pathTexture over blurTexture.
paint.addCoverageFragmentProcessor(
- GrSimpleTextureEffect::Make(src, nullptr, SkMatrix::I()));
+ GrSimpleTextureEffect::Make(context, std::move(srcProxy), nullptr, SkMatrix::I()));
if (kInner_SkBlurStyle == fBlurStyle) {
// inner: dst = dst * src
paint.setCoverageSetOpXPFactory(SkRegion::kIntersect_Op);
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 88b14f3..aeab9d1 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -807,6 +807,9 @@
desc.fSampleCnt = sampleCnt;
sk_sp<GrSurfaceProxy> rtp = GrSurfaceProxy::MakeDeferred(*this->caps(), desc, fit, budgeted);
+ if (!rtp) {
+ return nullptr;
+ }
return fDrawingManager->makeRenderTargetContext(std::move(rtp),
std::move(colorSpace),
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index 1e9ac9b..b8b1dc7 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -135,6 +135,10 @@
const GrSurfaceDesc& desc,
SkBackingFit fit,
SkBudgeted budgeted) {
+ if (desc.fWidth > caps.maxTextureSize() || desc.fHeight > caps.maxTextureSize()) {
+ return nullptr;
+ }
+
if (kRenderTarget_GrSurfaceFlag & desc.fFlags) {
// We know anything we instantiate later from this deferred path will be
// both texturable and renderable
diff --git a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
index c5f554f..66aba13 100644
--- a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
+++ b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp
@@ -115,12 +115,17 @@
}
pdman.set2fv(fImageIncrementUni, 1, imageIncrement);
if (conv.useBounds()) {
- const float* bounds = conv.bounds();
- if (Gr1DKernelEffect::kY_Direction == conv.direction() &&
- texture.origin() != kTopLeft_GrSurfaceOrigin) {
- pdman.set2f(fBoundsUni, 1.0f - bounds[1], 1.0f - bounds[0]);
+ const int* bounds = conv.bounds();
+ if (Gr1DKernelEffect::kX_Direction == conv.direction()) {
+ SkScalar inv = SkScalarInvert(SkIntToScalar(texture.width()));
+ pdman.set2f(fBoundsUni, inv * bounds[0], inv * bounds[1]);
} else {
- pdman.set2f(fBoundsUni, bounds[0], bounds[1]);
+ SkScalar inv = SkScalarInvert(SkIntToScalar(texture.height()));
+ if (texture.origin() != kTopLeft_GrSurfaceOrigin) {
+ pdman.set2f(fBoundsUni, 1.0f - (inv * bounds[1]), 1.0f - (inv * bounds[0]));
+ } else {
+ pdman.set2f(fBoundsUni, inv * bounds[1], inv * bounds[0]);
+ }
}
}
int width = Gr1DKernelEffect::WidthFromRadius(conv.radius());
@@ -144,8 +149,6 @@
}
///////////////////////////////////////////////////////////////////////////////
-
-
static void fill_in_1D_guassian_kernel(float* kernel, int width, float gaussianSigma, int radius) {
const float denom = 1.0f / (2.0f * gaussianSigma * gaussianSigma);
@@ -169,7 +172,7 @@
int radius,
float gaussianSigma,
bool useBounds,
- float bounds[2])
+ int bounds[2])
: INHERITED(texture, direction, radius, ModulationFlags(texture->config()))
, fUseBounds(useBounds) {
this->initClassID<GrGaussianConvolutionFragmentProcessor>();
@@ -187,7 +190,7 @@
int radius,
float gaussianSigma,
bool useBounds,
- float bounds[2])
+ int bounds[2])
: INHERITED{context,
ModulationFlags(proxy->config()),
GR_PROXY_MOVE(proxy),
@@ -230,16 +233,25 @@
GrProcessorTestData* d) {
int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
: GrProcessorUnitTest::kAlphaTextureIdx;
- Direction dir = d->fRandom->nextBool() ? kX_Direction : kY_Direction;
- int radius = d->fRandom->nextRangeU(1, kMaxKernelRadius);
+ sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
bool useBounds = d->fRandom->nextBool();
- float bounds[2];
- for (size_t i = 0; i < SK_ARRAY_COUNT(bounds); ++i) {
- bounds[i] = d->fRandom->nextF();
+ int bounds[2];
+
+ Direction dir;
+ if (d->fRandom->nextBool()) {
+ dir = kX_Direction;
+ bounds[0] = d->fRandom->nextRangeU(0, proxy->width()-1);
+ bounds[1] = d->fRandom->nextRangeU(bounds[0], proxy->width()-1);
+ } else {
+ dir = kY_Direction;
+ bounds[0] = d->fRandom->nextRangeU(0, proxy->height()-1);
+ bounds[1] = d->fRandom->nextRangeU(bounds[0], proxy->height()-1);
}
+ int radius = d->fRandom->nextRangeU(1, kMaxKernelRadius);
float sigma = radius / 3.f;
+
return GrGaussianConvolutionFragmentProcessor::Make(
d->context(), d->textureProxy(texIdx), dir, radius, sigma, useBounds, bounds);
}
diff --git a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h
index b4f5cb7..0bb9c5e 100644
--- a/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h
+++ b/src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h
@@ -24,7 +24,7 @@
int halfWidth,
float gaussianSigma,
bool useBounds,
- float* bounds) {
+ int* bounds) {
return sk_sp<GrFragmentProcessor>(new GrGaussianConvolutionFragmentProcessor(
tex, dir, halfWidth, gaussianSigma, useBounds, bounds));
}
@@ -35,7 +35,7 @@
int halfWidth,
float gaussianSigma,
bool useBounds,
- float* bounds) {
+ int* bounds) {
return sk_sp<GrFragmentProcessor>(new GrGaussianConvolutionFragmentProcessor(
context, std::move(proxy), dir, halfWidth, gaussianSigma, useBounds, bounds));
}
@@ -44,7 +44,7 @@
const float* kernel() const { return fKernel; }
- const float* bounds() const { return fBounds; }
+ const int* bounds() const { return fBounds; }
bool useBounds() const { return fUseBounds; }
const char* name() const override { return "GaussianConvolution"; }
@@ -61,11 +61,11 @@
private:
/// Convolve with a Gaussian kernel
GrGaussianConvolutionFragmentProcessor(GrTexture*, Direction, int halfWidth,
- float gaussianSigma, bool useBounds, float bounds[2]);
+ float gaussianSigma, bool useBounds, int bounds[2]);
GrGaussianConvolutionFragmentProcessor(GrContext*, sk_sp<GrTextureProxy>, Direction,
int halfWidth, float gaussianSigma, bool useBounds,
- float bounds[2]);
+ int bounds[2]);
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
@@ -85,7 +85,7 @@
// some of the logic from SkGpuBlurUtils into this class related to radius/sigma calculations.
float fKernel[kMaxKernelWidth];
bool fUseBounds;
- float fBounds[2];
+ int fBounds[2];
typedef Gr1DKernelEffect INHERITED;
};
diff --git a/src/gpu/effects/GrProxyMove.h b/src/gpu/effects/GrProxyMove.h
index 643e01b..87612f7 100644
--- a/src/gpu/effects/GrProxyMove.h
+++ b/src/gpu/effects/GrProxyMove.h
@@ -3,8 +3,8 @@
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
- */
-
+ */
+
#ifndef GrProxyMove_DEFINED
#define GrProxyMove_DEFINED