1 /*
2  * Copyright 2013 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkGpuBlurUtils_DEFINED
9 #define SkGpuBlurUtils_DEFINED
10 
11 #include "include/core/SkTypes.h"
12 
13 #if SK_SUPPORT_GPU
14 #include "src/gpu/GrSurfaceDrawContext.h"
15 
16 class GrRecordingContext;
17 class GrTexture;
18 
19 struct SkRect;
20 
21 namespace SkGpuBlurUtils {
22 
23 /** Maximum sigma before the implementation downscales the input image. */
24 static constexpr float kMaxSigma = 4.f;
25 
26 /**
27  * Applies a 2D Gaussian blur to a given texture. The blurred result is returned
28  * as a surfaceDrawContext in case the caller wishes to draw into the result.
29  * The GrSurfaceOrigin of the result will watch the GrSurfaceOrigin of srcView. The output
30  * color type, color space, and alpha type will be the same as the src.
31  *
32  * Note: one of sigmaX and sigmaY should be non-zero!
33  * @param context         The GPU context
34  * @param srcView         The source to be blurred.
35  * @param srcColorType    The colorType of srcProxy
36  * @param srcAlphaType    The alphaType of srcProxy
37  * @param colorSpace      Color space of the source.
38  * @param dstBounds       The destination bounds, relative to the source texture.
39  * @param srcBounds       The source bounds, relative to the source texture's offset. No pixels
40  *                        will be sampled outside of this rectangle.
41  * @param sigmaX          The blur's standard deviation in X.
42  * @param sigmaY          The blur's standard deviation in Y.
43  * @param tileMode        The mode to handle samples outside bounds.
44  * @param fit             backing fit for the returned render target context
45  * @return                The surfaceDrawContext containing the blurred result.
46  */
47 std::unique_ptr<GrSurfaceDrawContext> GaussianBlur(GrRecordingContext* context,
48                                                    GrSurfaceProxyView srcView,
49                                                    GrColorType srcColorType,
50                                                    SkAlphaType srcAlphaType,
51                                                    sk_sp<SkColorSpace> colorSpace,
52                                                    SkIRect dstBounds,
53                                                    SkIRect srcBounds,
54                                                    float sigmaX,
55                                                    float sigmaY,
56                                                    SkTileMode mode,
57                                                    SkBackingFit fit = SkBackingFit::kApprox);
58 
59 static const int kBlurRRectMaxDivisions = 6;
60 
61 // This method computes all the parameters for drawing a partially occluded nine-patched
62 // blurred rrect mask:
63 //   rrectToDraw - the integerized rrect to draw in the mask
64 //   widthHeight - how large to make the mask (rrectToDraw will be centered in this coord sys)
65 //   rectXs, rectYs - the x & y coordinates of the covering geometry lattice
66 //   texXs, texYs - the texture coordinate at each point in rectXs & rectYs
67 // It returns true if 'devRRect' is nine-patchable
68 bool ComputeBlurredRRectParams(const SkRRect& srcRRect, const SkRRect& devRRect,
69                                 SkScalar sigma, SkScalar xformedSigma,
70                                 SkRRect* rrectToDraw,
71                                 SkISize* widthHeight,
72                                 SkScalar rectXs[kBlurRRectMaxDivisions],
73                                 SkScalar rectYs[kBlurRRectMaxDivisions],
74                                 SkScalar texXs[kBlurRRectMaxDivisions],
75                                 SkScalar texYs[kBlurRRectMaxDivisions]);
76 
77 int CreateIntegralTable(float sixSigma, SkBitmap* table);
78 
79 void Compute1DGaussianKernel(float* kernel, float sigma, int radius);
80 
81 void Compute1DLinearGaussianKernel(float* kernel, float* offset, float sigma, int radius);
82 
83 // Any sigmas smaller than this are effectively an identity blur so can skip convolution at a higher
84 // level. The value was chosen because it corresponds roughly to a radius of 1/10px, and is slightly
85 // greater than sqrt(1/2*sigma^2) for SK_ScalarNearlyZero.
IsEffectivelyZeroSigma(float sigma)86 inline bool IsEffectivelyZeroSigma(float sigma) { return sigma <= 0.03f; }
87 
SigmaRadius(float sigma)88 inline int SigmaRadius(float sigma) {
89     return IsEffectivelyZeroSigma(sigma) ? 0 : static_cast<int>(ceilf(sigma * 3.0f));
90 }
91 
KernelWidth(int radius)92 inline int KernelWidth(int radius) { return 2 * radius + 1; }
93 
LinearKernelWidth(int radius)94 inline int LinearKernelWidth(int radius) { return radius + 1; }
95 
96 }  // namespace SkGpuBlurUtils
97 
98 #endif
99 #endif
100