Loading libs/renderengine/skia/filters/KawaseBlurDualFilter.cpp +50 −16 Original line number Diff line number Diff line Loading @@ -39,12 +39,36 @@ namespace renderengine { namespace skia { KawaseBlurDualFilter::KawaseBlurDualFilter() : BlurFilter() { // A shader to sample each vertex of a unit regular heptagon // plus the original fragment coordinate. SkString blurString(R"( // A shader to sample each vertex of a square, plus the original fragment coordinate, // using a total of 5 samples. SkString lowSampleBlurString(R"( uniform shader child; uniform float in_blurOffset; uniform float in_crossFade; uniform float in_weightedCrossFade; const float2 STEP_0 = float2( 0.707106781, 0.707106781); const float2 STEP_1 = float2( 0.707106781, -0.707106781); const float2 STEP_2 = float2(-0.707106781, -0.707106781); const float2 STEP_3 = float2(-0.707106781, 0.707106781); half4 main(float2 xy) { half3 c = child.eval(xy).rgb; c += child.eval(xy + STEP_0 * in_blurOffset).rgb; c += child.eval(xy + STEP_1 * in_blurOffset).rgb; c += child.eval(xy + STEP_2 * in_blurOffset).rgb; c += child.eval(xy + STEP_3 * in_blurOffset).rgb; return half4(c * in_weightedCrossFade, in_crossFade); } )"); // A shader to sample each vertex of a unit regular heptagon, plus the original fragment // coordinate, using a total of 8 samples. SkString highSampleBlurString(R"( uniform shader child; uniform float in_blurOffset; const float2 STEP_0 = float2( 1.0, 0.0); const float2 STEP_1 = float2( 0.623489802, 0.781831482); Loading @@ -65,39 +89,46 @@ KawaseBlurDualFilter::KawaseBlurDualFilter() : BlurFilter() { c += child.eval(xy + STEP_5 * in_blurOffset).rgb; c += child.eval(xy + STEP_6 * in_blurOffset).rgb; return half4(c * 0.125 * in_crossFade, in_crossFade); return half4(c * 0.125, 1.0); } )"); auto [blurEffect, error] = SkRuntimeEffect::MakeForShader(blurString); LOG_ALWAYS_FATAL_IF(!blurEffect, "RuntimeShader error: %s", error.c_str()); mBlurEffect = std::move(blurEffect); auto [lowSampleBlurEffect, error] = SkRuntimeEffect::MakeForShader(lowSampleBlurString); auto [highSampleBlurEffect, error2] = SkRuntimeEffect::MakeForShader(highSampleBlurString); LOG_ALWAYS_FATAL_IF(!lowSampleBlurEffect, "RuntimeShader error: %s", error.c_str()); LOG_ALWAYS_FATAL_IF(!highSampleBlurEffect, "RuntimeShader error: %s", error2.c_str()); mLowSampleBlurEffect = std::move(lowSampleBlurEffect); mHighSampleBlurEffect = std::move(highSampleBlurEffect); } void KawaseBlurDualFilter::blurInto(const sk_sp<SkSurface>& drawSurface, const sk_sp<SkImage>& readImage, const float radius, const float alpha) const { const float alpha, const sk_sp<SkRuntimeEffect>& blurEffect) const { const float scale = static_cast<float>(drawSurface->width()) / readImage->width(); SkMatrix blurMatrix = SkMatrix::Scale(scale, scale); blurInto(drawSurface, readImage->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone), blurMatrix), readImage->width() / static_cast<float>(drawSurface->width()), radius, alpha); radius, alpha, blurEffect); } void KawaseBlurDualFilter::blurInto(const sk_sp<SkSurface>& drawSurface, sk_sp<SkShader> input, const float inverseScale, const float radius, const float alpha) const { const float radius, const float alpha, const sk_sp<SkRuntimeEffect>& blurEffect) const { SkPaint paint; if (radius == 0) { paint.setShader(std::move(input)); paint.setAlphaf(alpha); } else { SkRuntimeShaderBuilder blurBuilder(mBlurEffect); SkRuntimeShaderBuilder blurBuilder(blurEffect); blurBuilder.child("child") = std::move(input); blurBuilder.uniform("in_blurOffset") = radius; if (blurEffect == mLowSampleBlurEffect) { blurBuilder.uniform("in_crossFade") = alpha; blurBuilder.uniform("in_weightedCrossFade") = alpha * 0.2f; } blurBuilder.uniform("in_blurOffset") = radius; paint.setShader(blurBuilder.makeShader(nullptr)); } paint.setBlendMode(alpha == 1.0f ? SkBlendMode::kSrc : SkBlendMode::kSrcOver); Loading Loading @@ -163,16 +194,19 @@ sk_sp<SkImage> KawaseBlurDualFilter::generate(SkiaGpuContext* context, const uin input->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone), blurMatrix); blurInto(surfaces[0], std::move(sourceShader), kInputScale, kWeights[0] * step, 1.0f); blurInto(surfaces[0], std::move(sourceShader), kWeights[0] * step, 1.0f, mLowSampleBlurEffect); } // Next the remaining downscale blur passes. for (int i = 0; i < filterPasses; i++) { blurInto(surfaces[i + 1], surfaces[i]->makeTemporaryImage(), kWeights[1 + i] * step, 1.0f); // Blur with the higher sample effect into the smaller buffers, for better visual quality. blurInto(surfaces[i + 1], surfaces[i]->makeTemporaryImage(), kWeights[1 + i] * step, 1.0f, i == 0 ? mLowSampleBlurEffect : mHighSampleBlurEffect); } // Finally blur+upscale back to our original size. for (int i = filterPasses - 1; i >= 0; i--) { blurInto(surfaces[i], surfaces[i + 1]->makeTemporaryImage(), kWeights[4 - i] * step, std::min(1.0f, filterDepth - i)); std::min(1.0f, filterDepth - i), mLowSampleBlurEffect); } return surfaces[0]->makeTemporaryImage(); } Loading libs/renderengine/skia/filters/KawaseBlurDualFilter.h +4 −3 Original line number Diff line number Diff line Loading @@ -41,13 +41,14 @@ public: const sk_sp<SkImage> blurInput, const SkRect& blurRect) const override; private: sk_sp<SkRuntimeEffect> mBlurEffect; sk_sp<SkRuntimeEffect> mLowSampleBlurEffect; sk_sp<SkRuntimeEffect> mHighSampleBlurEffect; void blurInto(const sk_sp<SkSurface>& drawSurface, const sk_sp<SkImage>& readImage, const float radius, const float alpha) const; const float radius, const float alpha, const sk_sp<SkRuntimeEffect>&) const; void blurInto(const sk_sp<SkSurface>& drawSurface, const sk_sp<SkShader> input, const float inverseScale, const float radius, const float alpha) const; const float radius, const float alpha, const sk_sp<SkRuntimeEffect>&) const; }; } // namespace skia Loading Loading
libs/renderengine/skia/filters/KawaseBlurDualFilter.cpp +50 −16 Original line number Diff line number Diff line Loading @@ -39,12 +39,36 @@ namespace renderengine { namespace skia { KawaseBlurDualFilter::KawaseBlurDualFilter() : BlurFilter() { // A shader to sample each vertex of a unit regular heptagon // plus the original fragment coordinate. SkString blurString(R"( // A shader to sample each vertex of a square, plus the original fragment coordinate, // using a total of 5 samples. SkString lowSampleBlurString(R"( uniform shader child; uniform float in_blurOffset; uniform float in_crossFade; uniform float in_weightedCrossFade; const float2 STEP_0 = float2( 0.707106781, 0.707106781); const float2 STEP_1 = float2( 0.707106781, -0.707106781); const float2 STEP_2 = float2(-0.707106781, -0.707106781); const float2 STEP_3 = float2(-0.707106781, 0.707106781); half4 main(float2 xy) { half3 c = child.eval(xy).rgb; c += child.eval(xy + STEP_0 * in_blurOffset).rgb; c += child.eval(xy + STEP_1 * in_blurOffset).rgb; c += child.eval(xy + STEP_2 * in_blurOffset).rgb; c += child.eval(xy + STEP_3 * in_blurOffset).rgb; return half4(c * in_weightedCrossFade, in_crossFade); } )"); // A shader to sample each vertex of a unit regular heptagon, plus the original fragment // coordinate, using a total of 8 samples. SkString highSampleBlurString(R"( uniform shader child; uniform float in_blurOffset; const float2 STEP_0 = float2( 1.0, 0.0); const float2 STEP_1 = float2( 0.623489802, 0.781831482); Loading @@ -65,39 +89,46 @@ KawaseBlurDualFilter::KawaseBlurDualFilter() : BlurFilter() { c += child.eval(xy + STEP_5 * in_blurOffset).rgb; c += child.eval(xy + STEP_6 * in_blurOffset).rgb; return half4(c * 0.125 * in_crossFade, in_crossFade); return half4(c * 0.125, 1.0); } )"); auto [blurEffect, error] = SkRuntimeEffect::MakeForShader(blurString); LOG_ALWAYS_FATAL_IF(!blurEffect, "RuntimeShader error: %s", error.c_str()); mBlurEffect = std::move(blurEffect); auto [lowSampleBlurEffect, error] = SkRuntimeEffect::MakeForShader(lowSampleBlurString); auto [highSampleBlurEffect, error2] = SkRuntimeEffect::MakeForShader(highSampleBlurString); LOG_ALWAYS_FATAL_IF(!lowSampleBlurEffect, "RuntimeShader error: %s", error.c_str()); LOG_ALWAYS_FATAL_IF(!highSampleBlurEffect, "RuntimeShader error: %s", error2.c_str()); mLowSampleBlurEffect = std::move(lowSampleBlurEffect); mHighSampleBlurEffect = std::move(highSampleBlurEffect); } void KawaseBlurDualFilter::blurInto(const sk_sp<SkSurface>& drawSurface, const sk_sp<SkImage>& readImage, const float radius, const float alpha) const { const float alpha, const sk_sp<SkRuntimeEffect>& blurEffect) const { const float scale = static_cast<float>(drawSurface->width()) / readImage->width(); SkMatrix blurMatrix = SkMatrix::Scale(scale, scale); blurInto(drawSurface, readImage->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone), blurMatrix), readImage->width() / static_cast<float>(drawSurface->width()), radius, alpha); radius, alpha, blurEffect); } void KawaseBlurDualFilter::blurInto(const sk_sp<SkSurface>& drawSurface, sk_sp<SkShader> input, const float inverseScale, const float radius, const float alpha) const { const float radius, const float alpha, const sk_sp<SkRuntimeEffect>& blurEffect) const { SkPaint paint; if (radius == 0) { paint.setShader(std::move(input)); paint.setAlphaf(alpha); } else { SkRuntimeShaderBuilder blurBuilder(mBlurEffect); SkRuntimeShaderBuilder blurBuilder(blurEffect); blurBuilder.child("child") = std::move(input); blurBuilder.uniform("in_blurOffset") = radius; if (blurEffect == mLowSampleBlurEffect) { blurBuilder.uniform("in_crossFade") = alpha; blurBuilder.uniform("in_weightedCrossFade") = alpha * 0.2f; } blurBuilder.uniform("in_blurOffset") = radius; paint.setShader(blurBuilder.makeShader(nullptr)); } paint.setBlendMode(alpha == 1.0f ? SkBlendMode::kSrc : SkBlendMode::kSrcOver); Loading Loading @@ -163,16 +194,19 @@ sk_sp<SkImage> KawaseBlurDualFilter::generate(SkiaGpuContext* context, const uin input->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone), blurMatrix); blurInto(surfaces[0], std::move(sourceShader), kInputScale, kWeights[0] * step, 1.0f); blurInto(surfaces[0], std::move(sourceShader), kWeights[0] * step, 1.0f, mLowSampleBlurEffect); } // Next the remaining downscale blur passes. for (int i = 0; i < filterPasses; i++) { blurInto(surfaces[i + 1], surfaces[i]->makeTemporaryImage(), kWeights[1 + i] * step, 1.0f); // Blur with the higher sample effect into the smaller buffers, for better visual quality. blurInto(surfaces[i + 1], surfaces[i]->makeTemporaryImage(), kWeights[1 + i] * step, 1.0f, i == 0 ? mLowSampleBlurEffect : mHighSampleBlurEffect); } // Finally blur+upscale back to our original size. for (int i = filterPasses - 1; i >= 0; i--) { blurInto(surfaces[i], surfaces[i + 1]->makeTemporaryImage(), kWeights[4 - i] * step, std::min(1.0f, filterDepth - i)); std::min(1.0f, filterDepth - i), mLowSampleBlurEffect); } return surfaces[0]->makeTemporaryImage(); } Loading
libs/renderengine/skia/filters/KawaseBlurDualFilter.h +4 −3 Original line number Diff line number Diff line Loading @@ -41,13 +41,14 @@ public: const sk_sp<SkImage> blurInput, const SkRect& blurRect) const override; private: sk_sp<SkRuntimeEffect> mBlurEffect; sk_sp<SkRuntimeEffect> mLowSampleBlurEffect; sk_sp<SkRuntimeEffect> mHighSampleBlurEffect; void blurInto(const sk_sp<SkSurface>& drawSurface, const sk_sp<SkImage>& readImage, const float radius, const float alpha) const; const float radius, const float alpha, const sk_sp<SkRuntimeEffect>&) const; void blurInto(const sk_sp<SkSurface>& drawSurface, const sk_sp<SkShader> input, const float inverseScale, const float radius, const float alpha) const; const float radius, const float alpha, const sk_sp<SkRuntimeEffect>&) const; }; } // namespace skia Loading