blob: 68100e95d206094fe6feebbf2f70e07aeb3eda3c [file] [log] [blame]
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkGpuBlurUtils_DEFINED
#define SkGpuBlurUtils_DEFINED
#include "include/core/SkTypes.h"
#if SK_SUPPORT_GPU
#include "src/gpu/GrSurfaceDrawContext.h"
class GrRecordingContext;
class GrTexture;
struct SkRect;
namespace SkGpuBlurUtils {
/** Maximum sigma before the implementation downscales the input image. */
static constexpr float kMaxSigma = 4.f;
#if GR_OGA
/**
* Applies a 2D Gaussian blur to a given texture. The blurred result is returned
* as a surfaceDrawContext in case the caller wishes to draw into the result.
* The GrSurfaceOrigin of the result will watch the GrSurfaceOrigin of srcView. The output
* color type, color space, and alpha type will be the same as the src.
*
* Note: one of sigmaX and sigmaY should be non-zero!
* @param context The GPU context
* @param srcView The source to be blurred.
* @param srcColorType The colorType of srcProxy
* @param srcAlphaType The alphaType of srcProxy
* @param colorSpace Color space of the source.
* @param dstBounds The destination bounds, relative to the source texture.
* @param srcBounds The source bounds, relative to the source texture's offset. No pixels
* will be sampled outside of this rectangle.
* @param sigmaX The blur's standard deviation in X.
* @param sigmaY The blur's standard deviation in Y.
* @param tileMode The mode to handle samples outside bounds.
* @param fit backing fit for the returned render target context
* @return The surfaceDrawContext containing the blurred result.
*/
std::unique_ptr<GrSurfaceDrawContext> GaussianBlur(GrRecordingContext* context,
GrSurfaceProxyView srcView,
GrColorType srcColorType,
SkAlphaType srcAlphaType,
sk_sp<SkColorSpace> colorSpace,
SkIRect dstBounds,
SkIRect srcBounds,
float sigmaX,
float sigmaY,
SkTileMode mode,
SkBackingFit fit = SkBackingFit::kApprox);
#endif
static const int kBlurRRectMaxDivisions = 6;
// This method computes all the parameters for drawing a partially occluded nine-patched
// blurred rrect mask:
// rrectToDraw - the integerized rrect to draw in the mask
// widthHeight - how large to make the mask (rrectToDraw will be centered in this coord sys)
// rectXs, rectYs - the x & y coordinates of the covering geometry lattice
// texXs, texYs - the texture coordinate at each point in rectXs & rectYs
// It returns true if 'devRRect' is nine-patchable
bool ComputeBlurredRRectParams(const SkRRect& srcRRect, const SkRRect& devRRect,
SkScalar sigma, SkScalar xformedSigma,
SkRRect* rrectToDraw,
SkISize* widthHeight,
SkScalar rectXs[kBlurRRectMaxDivisions],
SkScalar rectYs[kBlurRRectMaxDivisions],
SkScalar texXs[kBlurRRectMaxDivisions],
SkScalar texYs[kBlurRRectMaxDivisions]);
int CreateIntegralTable(float sixSigma, SkBitmap* table);
void Compute1DGaussianKernel(float* kernel, float sigma, int radius);
void Compute1DLinearGaussianKernel(float* kernel, float* offset, float sigma, int radius);
// Any sigmas smaller than this are effectively an identity blur so can skip convolution at a higher
// level. The value was chosen because it corresponds roughly to a radius of 1/10px, and is slightly
// greater than sqrt(1/2*sigma^2) for SK_ScalarNearlyZero.
inline bool IsEffectivelyZeroSigma(float sigma) { return sigma <= 0.03f; }
inline int SigmaRadius(float sigma) {
return IsEffectivelyZeroSigma(sigma) ? 0 : static_cast<int>(ceilf(sigma * 3.0f));
}
inline int KernelWidth(int radius) { return 2 * radius + 1; }
inline int LinearKernelWidth(int radius) { return radius + 1; }
} // namespace SkGpuBlurUtils
#endif
#endif