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 "include/core/SkRefCnt.h"
15 #include "include/private/GrTypesPriv.h"
16
17 class GrRecordingContext;
18 namespace skgpu { namespace v1 { class SurfaceDrawContext; }}
19 class GrSurfaceProxyView;
20 class GrTexture;
21
22 struct SkRect;
23
24 namespace SkGpuBlurUtils {
25
26 /** Maximum sigma before the implementation downscales the input image. */
27 static constexpr float kMaxSigma = 4.f;
28
29 #if SK_GPU_V1
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 #endif // SK_GPU_V1
64
65 static const int kBlurRRectMaxDivisions = 6;
66
67 // This method computes all the parameters for drawing a partially occluded nine-patched
68 // blurred rrect mask:
69 // rrectToDraw - the integerized rrect to draw in the mask
70 // widthHeight - how large to make the mask (rrectToDraw will be centered in this coord sys)
71 // rectXs, rectYs - the x & y coordinates of the covering geometry lattice
72 // texXs, texYs - the texture coordinate at each point in rectXs & rectYs
73 // It returns true if 'devRRect' is nine-patchable
74 bool ComputeBlurredRRectParams(const SkRRect& srcRRect,
75 const SkRRect& devRRect,
76 SkScalar sigma,
77 SkScalar xformedSigma,
78 SkRRect* rrectToDraw,
79 SkISize* widthHeight,
80 SkScalar rectXs[kBlurRRectMaxDivisions],
81 SkScalar rectYs[kBlurRRectMaxDivisions],
82 SkScalar texXs[kBlurRRectMaxDivisions],
83 SkScalar texYs[kBlurRRectMaxDivisions]);
84
85 int CreateIntegralTable(float sixSigma, SkBitmap* table);
86
87 void Compute1DGaussianKernel(float* kernel, float sigma, int radius);
88
89 void Compute1DLinearGaussianKernel(float* kernel, float* offset, float sigma, int radius);
90
91 // Any sigmas smaller than this are effectively an identity blur so can skip convolution at a higher
92 // level. The value was chosen because it corresponds roughly to a radius of 1/10px, and is slightly
93 // greater than sqrt(1/2*sigma^2) for SK_ScalarNearlyZero.
IsEffectivelyZeroSigma(float sigma)94 inline bool IsEffectivelyZeroSigma(float sigma) { return sigma <= 0.03f; }
95
SigmaRadius(float sigma)96 inline int SigmaRadius(float sigma) {
97 return IsEffectivelyZeroSigma(sigma) ? 0 : static_cast<int>(ceilf(sigma * 3.0f));
98 }
99
KernelWidth(int radius)100 inline int KernelWidth(int radius) { return 2 * radius + 1; }
101
LinearKernelWidth(int radius)102 inline int LinearKernelWidth(int radius) { return radius + 1; }
103
104 } // namespace SkGpuBlurUtils
105
106 #endif // SK_SUPPORT_GPU
107
108 #endif
109