Flutter Engine
The Flutter Engine
Public Member Functions | Static Public Member Functions | Static Public Attributes | List of all members
KawaseBlurFilter Class Reference

Public Member Functions

 KawaseBlurFilter ()
 
void draw (SkCanvas *canvas, sk_sp< SkImage > input, int blurRadius)
 

Static Public Member Functions

static sk_sp< SkSurfaceMakeSurface (SkCanvas *canvas, const SkImageInfo &info)
 

Static Public Attributes

static constexpr float kInputScale = 0.25f
 
static constexpr float kInverseInputScale = 1.0f / kInputScale
 
static constexpr uint32_t kMaxPasses = 4
 
static constexpr float kMaxCrossFadeRadius = 30.0f
 

Detailed Description

Definition at line 19 of file kawase_blur_rt.cpp.

Constructor & Destructor Documentation

◆ KawaseBlurFilter()

KawaseBlurFilter::KawaseBlurFilter ( )
inline

Definition at line 31 of file kawase_blur_rt.cpp.

31 {
32 SkString blurString(R"(
33 uniform shader src;
34 uniform float in_inverseScale;
35 uniform float2 in_blurOffset;
36
37 half4 main(float2 xy) {
38 float2 scaled_xy = float2(xy.x * in_inverseScale, xy.y * in_inverseScale);
39
40 half4 c = src.eval(scaled_xy);
41 c += src.eval(scaled_xy + float2( in_blurOffset.x, in_blurOffset.y));
42 c += src.eval(scaled_xy + float2( in_blurOffset.x, -in_blurOffset.y));
43 c += src.eval(scaled_xy + float2(-in_blurOffset.x, in_blurOffset.y));
44 c += src.eval(scaled_xy + float2(-in_blurOffset.x, -in_blurOffset.y));
45
46 return half4(c.rgb * 0.2, 1.0);
47 }
48 )");
49
50 SkString mixString(R"(
51 uniform shader in_blur;
52 uniform shader in_original;
53 uniform float in_inverseScale;
54 uniform float in_mix;
55
56 half4 main(float2 xy) {
57 float2 scaled_xy = float2(xy.x * in_inverseScale, xy.y * in_inverseScale);
58
59 half4 blurred = in_blur.eval(scaled_xy);
60 half4 composition = in_original.eval(xy);
61 return mix(composition, blurred, in_mix);
62 }
63 )");
64
65 auto [blurEffect, error] = SkRuntimeEffect::MakeForShader(blurString);
66 if (!blurEffect) {
67 SkDEBUGFAILF("RuntimeShader error: %s\n", error.c_str());
68 }
69 fBlurEffect = std::move(blurEffect);
70
71 auto [mixEffect, error2] = SkRuntimeEffect::MakeForShader(mixString);
72 if (!mixEffect) {
73 SkDEBUGFAILF("RuntimeShader error: %s\n", error2.c_str());
74 }
75 fMixEffect = std::move(mixEffect);
76 }
#define SkDEBUGFAILF(fmt,...)
Definition: SkAssert.h:119
static Result MakeForShader(SkString sksl, const Options &)
const uint8_t uint32_t uint32_t GError ** error

Member Function Documentation

◆ draw()

void KawaseBlurFilter::draw ( SkCanvas canvas,
sk_sp< SkImage input,
int  blurRadius 
)
inline

Definition at line 86 of file kawase_blur_rt.cpp.

86 {
87 // NOTE: this is only experimental and the current blur params cause points to be sampled
88 // beyond the input blur radius.
89
90 // Kawase is an approximation of Gaussian, but it behaves differently from it.
91 // A radius transformation is required for approximating them, and also to introduce
92 // non-integer steps, necessary to smoothly interpolate large radii.
93 float tmpRadius = (float)blurRadius / 6.0f;
94 float numberOfPasses = std::min(kMaxPasses, (uint32_t)ceil(tmpRadius));
95 float radiusByPasses = tmpRadius / (float)numberOfPasses;
96
97 SkImageInfo scaledInfo = SkImageInfo::MakeN32Premul((float)input->width() * kInputScale,
98 (float)input->height() * kInputScale);
99 auto drawSurface = MakeSurface(canvas, scaledInfo);
100
101 const float stepX = radiusByPasses;
102 const float stepY = radiusByPasses;
103
104 // start by drawing and downscaling and doing the first blur pass
105 SkRuntimeShaderBuilder blurBuilder(fBlurEffect);
106 blurBuilder.child("src") = input->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
107 blurBuilder.uniform("in_inverseScale") = kInverseInputScale;
108 blurBuilder.uniform("in_blurOffset") = SkV2{stepX * kInverseInputScale,
109 stepY * kInverseInputScale};
111 paint.setShader(blurBuilder.makeShader());
112 drawSurface->getCanvas()->drawIRect(scaledInfo.bounds(), paint);
113
114 // DEBUG draw each of the stages
115 canvas->save();
116 canvas->drawImage(drawSurface->makeImageSnapshot(), input->width() / 4, 0,
118 canvas->translate(input->width() / 4, input->height() * 0.75);
119
120 // And now we'll ping pong between our surfaces, to accumulate the result of various
121 // offsets.
122 auto lastDrawTarget = drawSurface;
123 if (numberOfPasses > 1) {
124 auto readSurface = drawSurface;
125 drawSurface = MakeSurface(canvas, scaledInfo);
126
127 for (auto i = 1; i < numberOfPasses; i++) {
128 const float stepScale = (float)i * kInputScale;
129
130 blurBuilder.child("src") = readSurface->makeImageSnapshot()->makeShader(
132 blurBuilder.uniform("in_inverseScale") = 1.0f;
133 blurBuilder.uniform("in_blurOffset") = SkV2{stepX * stepScale , stepY * stepScale};
134
135 paint.setShader(blurBuilder.makeShader());
136 drawSurface->getCanvas()->drawIRect(scaledInfo.bounds(), paint);
137
138 // DEBUG draw each of the stages
139 canvas->drawImage(drawSurface->makeImageSnapshot(), 0, 0, SkSamplingOptions());
140 canvas->translate(0, input->height() * 0.75);
141
142 // Swap buffers for next iteration
143 auto tmp = drawSurface;
144 drawSurface = readSurface;
145 readSurface = tmp;
146 }
147 lastDrawTarget = readSurface;
148 }
149
150 // restore translations done for debug and offset
151 canvas->restore();
152 SkAutoCanvasRestore acr(canvas, true);
153 canvas->translate(input->width(), 0);
154
155 // do the final composition and when we scale our blur up. It will be interpolated
156 // with the larger composited texture to hide downscaling artifacts.
157 SkRuntimeShaderBuilder mixBuilder(fMixEffect);
158 mixBuilder.child("in_blur") = lastDrawTarget->makeImageSnapshot()->makeShader(
160 mixBuilder.child("in_original") =
162 mixBuilder.uniform("in_inverseScale") = kInputScale;
163 mixBuilder.uniform("in_mix") = std::min(1.0f, (float)blurRadius / kMaxCrossFadeRadius);
164
165 paint.setShader(mixBuilder.makeShader());
166 canvas->drawIRect(input->bounds(), paint);
167 }
static constexpr float kInverseInputScale
static constexpr float kMaxCrossFadeRadius
static constexpr float kInputScale
static constexpr uint32_t kMaxPasses
static sk_sp< SkSurface > MakeSurface(SkCanvas *canvas, const SkImageInfo &info)
void restore()
Definition: SkCanvas.cpp:461
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
void drawIRect(const SkIRect &rect, const SkPaint &paint)
Definition: SkCanvas.h:1358
int save()
Definition: SkCanvas.cpp:447
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528
int width() const
Definition: SkImage.h:285
sk_sp< SkShader > makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions &, const SkMatrix *localMatrix=nullptr) const
Definition: SkImage.cpp:179
int height() const
Definition: SkImage.h:291
SkIRect bounds() const
Definition: SkImage.h:303
const Paint & paint
Definition: color_source.cc:38
static float min(float r, float g, float b)
Definition: hsl.cpp:48
SkSamplingOptions(SkFilterMode::kLinear))
SIN Vec< N, float > ceil(const Vec< N, float > &x)
Definition: SkVx.h:702
static SkImageInfo MakeN32Premul(int width, int height)
SkIRect bounds() const
Definition: SkImageInfo.h:427
Definition: SkM44.h:19

◆ MakeSurface()

static sk_sp< SkSurface > KawaseBlurFilter::MakeSurface ( SkCanvas canvas,
const SkImageInfo info 
)
inlinestatic

Definition at line 78 of file kawase_blur_rt.cpp.

78 {
80 return surface;
81 }
82 // serialize-8888 returns null from makeSurface; fallback to a raster surface.
84 }
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
sk_sp< SkSurface > makeSurface(const SkImageInfo &info, const SkSurfaceProps *props=nullptr)
Definition: SkCanvas.cpp:1195
VkSurfaceKHR surface
Definition: main.cc:49
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)

Member Data Documentation

◆ kInputScale

constexpr float KawaseBlurFilter::kInputScale = 0.25f
staticconstexpr

Definition at line 22 of file kawase_blur_rt.cpp.

◆ kInverseInputScale

constexpr float KawaseBlurFilter::kInverseInputScale = 1.0f / kInputScale
staticconstexpr

Definition at line 24 of file kawase_blur_rt.cpp.

◆ kMaxCrossFadeRadius

constexpr float KawaseBlurFilter::kMaxCrossFadeRadius = 30.0f
staticconstexpr

Definition at line 29 of file kawase_blur_rt.cpp.

◆ kMaxPasses

constexpr uint32_t KawaseBlurFilter::kMaxPasses = 4
staticconstexpr

Definition at line 26 of file kawase_blur_rt.cpp.


The documentation for this class was generated from the following file: