@@ -39,12 +39,36 @@ namespace renderengine {
3939namespace skia {
4040
4141KawaseBlurDualFilter::KawaseBlurDualFilter () : BlurFilter() {
42- // A shader to sample each vertex of a unit regular heptagon
43- // plus the original fragment coordinate .
44- SkString blurString (R"(
42+ // A shader to sample each vertex of a square, plus the original fragment coordinate,
43+ // using a total of 5 samples .
44+ SkString lowSampleBlurString (R"(
4545 uniform shader child;
4646 uniform float in_blurOffset;
4747 uniform float in_crossFade;
48+ uniform float in_weightedCrossFade;
49+
50+ const float2 STEP_0 = float2( 0.707106781, 0.707106781);
51+ const float2 STEP_1 = float2( 0.707106781, -0.707106781);
52+ const float2 STEP_2 = float2(-0.707106781, -0.707106781);
53+ const float2 STEP_3 = float2(-0.707106781, 0.707106781);
54+
55+ half4 main(float2 xy) {
56+ half3 c = child.eval(xy).rgb;
57+
58+ c += child.eval(xy + STEP_0 * in_blurOffset).rgb;
59+ c += child.eval(xy + STEP_1 * in_blurOffset).rgb;
60+ c += child.eval(xy + STEP_2 * in_blurOffset).rgb;
61+ c += child.eval(xy + STEP_3 * in_blurOffset).rgb;
62+
63+ return half4(c * in_weightedCrossFade, in_crossFade);
64+ }
65+ )" );
66+
67+ // A shader to sample each vertex of a unit regular heptagon, plus the original fragment
68+ // coordinate, using a total of 8 samples.
69+ SkString highSampleBlurString (R"(
70+ uniform shader child;
71+ uniform float in_blurOffset;
4872
4973 const float2 STEP_0 = float2( 1.0, 0.0);
5074 const float2 STEP_1 = float2( 0.623489802, 0.781831482);
@@ -65,39 +89,46 @@ KawaseBlurDualFilter::KawaseBlurDualFilter() : BlurFilter() {
6589 c += child.eval(xy + STEP_5 * in_blurOffset).rgb;
6690 c += child.eval(xy + STEP_6 * in_blurOffset).rgb;
6791
68- return half4(c * 0.125 * in_crossFade, in_crossFade );
92+ return half4(c * 0.125, 1.0 );
6993 }
7094 )" );
7195
72- auto [blurEffect, error] = SkRuntimeEffect::MakeForShader (blurString);
73- LOG_ALWAYS_FATAL_IF (!blurEffect, " RuntimeShader error: %s" , error.c_str ());
74- mBlurEffect = std::move (blurEffect);
96+ auto [lowSampleBlurEffect, error] = SkRuntimeEffect::MakeForShader (lowSampleBlurString);
97+ auto [highSampleBlurEffect, error2] = SkRuntimeEffect::MakeForShader (highSampleBlurString);
98+ LOG_ALWAYS_FATAL_IF (!lowSampleBlurEffect, " RuntimeShader error: %s" , error.c_str ());
99+ LOG_ALWAYS_FATAL_IF (!highSampleBlurEffect, " RuntimeShader error: %s" , error2.c_str ());
100+ mLowSampleBlurEffect = std::move (lowSampleBlurEffect);
101+ mHighSampleBlurEffect = std::move (highSampleBlurEffect);
75102}
76103
77104void KawaseBlurDualFilter::blurInto (const sk_sp<SkSurface>& drawSurface,
78105 const sk_sp<SkImage>& readImage, const float radius,
79- const float alpha) const {
106+ const float alpha,
107+ const sk_sp<SkRuntimeEffect>& blurEffect) const {
80108 const float scale = static_cast <float >(drawSurface->width ()) / readImage->width ();
81109 SkMatrix blurMatrix = SkMatrix::Scale (scale, scale);
82110 blurInto (drawSurface,
83111 readImage->makeShader (SkTileMode::kClamp , SkTileMode::kClamp ,
84112 SkSamplingOptions (SkFilterMode::kLinear , SkMipmapMode::kNone ),
85113 blurMatrix),
86- readImage-> width () / static_cast < float >(drawSurface-> width ()), radius, alpha);
114+ radius, alpha, blurEffect );
87115}
88116
89117void KawaseBlurDualFilter::blurInto (const sk_sp<SkSurface>& drawSurface, sk_sp<SkShader> input,
90- const float inverseScale , const float radius ,
91- const float alpha ) const {
118+ const float radius , const float alpha ,
119+ const sk_sp<SkRuntimeEffect>& blurEffect ) const {
92120 SkPaint paint;
93121 if (radius == 0 ) {
94122 paint.setShader (std::move (input));
95123 paint.setAlphaf (alpha);
96124 } else {
97- SkRuntimeShaderBuilder blurBuilder (mBlurEffect );
125+ SkRuntimeShaderBuilder blurBuilder (blurEffect );
98126 blurBuilder.child (" child" ) = std::move (input);
127+ if (blurEffect == mLowSampleBlurEffect ) {
128+ blurBuilder.uniform (" in_crossFade" ) = alpha;
129+ blurBuilder.uniform (" in_weightedCrossFade" ) = alpha * 0 .2f ;
130+ }
99131 blurBuilder.uniform (" in_blurOffset" ) = radius;
100- blurBuilder.uniform (" in_crossFade" ) = alpha;
101132 paint.setShader (blurBuilder.makeShader (nullptr ));
102133 }
103134 paint.setBlendMode (alpha == 1 .0f ? SkBlendMode::kSrc : SkBlendMode::kSrcOver );
@@ -163,16 +194,19 @@ sk_sp<SkImage> KawaseBlurDualFilter::generate(SkiaGpuContext* context, const uin
163194 input->makeShader (SkTileMode::kClamp , SkTileMode::kClamp ,
164195 SkSamplingOptions (SkFilterMode::kLinear , SkMipmapMode::kNone ),
165196 blurMatrix);
166- blurInto (surfaces[0 ], std::move (sourceShader), kInputScale , kWeights [0 ] * step, 1 .0f );
197+ blurInto (surfaces[0 ], std::move (sourceShader), kWeights [0 ] * step, 1 .0f ,
198+ mLowSampleBlurEffect );
167199 }
168200 // Next the remaining downscale blur passes.
169201 for (int i = 0 ; i < filterPasses; i++) {
170- blurInto (surfaces[i + 1 ], surfaces[i]->makeTemporaryImage (), kWeights [1 + i] * step, 1 .0f );
202+ // Blur with the higher sample effect into the smaller buffers, for better visual quality.
203+ blurInto (surfaces[i + 1 ], surfaces[i]->makeTemporaryImage (), kWeights [1 + i] * step, 1 .0f ,
204+ i == 0 ? mLowSampleBlurEffect : mHighSampleBlurEffect );
171205 }
172206 // Finally blur+upscale back to our original size.
173207 for (int i = filterPasses - 1 ; i >= 0 ; i--) {
174208 blurInto (surfaces[i], surfaces[i + 1 ]->makeTemporaryImage (), kWeights [4 - i] * step,
175- std::min (1 .0f , filterDepth - i));
209+ std::min (1 .0f , filterDepth - i), mLowSampleBlurEffect );
176210 }
177211 return surfaces[0 ]->makeTemporaryImage ();
178212}
0 commit comments