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