From 877c524e5ed75766d918f8f46bf82ec9cb9b4c52 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Sat, 23 Nov 2024 00:52:06 +0900 Subject: [PATCH] renderer/sw_engine: fix omitted alpha multiplication in the dropshadow effect When a scene has a valid opacity, it must be multiplied with the direct dropshadow image to ensure correct rendering. --- src/renderer/gl_engine/tvgGlRenderer.cpp | 2 +- src/renderer/gl_engine/tvgGlRenderer.h | 2 +- src/renderer/sw_engine/tvgSwCommon.h | 4 ++-- src/renderer/sw_engine/tvgSwPostEffect.cpp | 8 ++++---- src/renderer/sw_engine/tvgSwRenderer.cpp | 6 +++--- src/renderer/sw_engine/tvgSwRenderer.h | 2 +- src/renderer/tvgRender.h | 2 +- src/renderer/tvgScene.h | 2 +- src/renderer/wg_engine/tvgWgRenderer.cpp | 2 +- src/renderer/wg_engine/tvgWgRenderer.h | 2 +- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/renderer/gl_engine/tvgGlRenderer.cpp b/src/renderer/gl_engine/tvgGlRenderer.cpp index 3242462c..bb06b4f1 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.cpp +++ b/src/renderer/gl_engine/tvgGlRenderer.cpp @@ -982,7 +982,7 @@ bool GlRenderer::prepare(TVG_UNUSED RenderEffect* effect) } -bool GlRenderer::effect(TVG_UNUSED RenderCompositor* cmp, TVG_UNUSED const RenderEffect* effect, TVG_UNUSED bool direct) +bool GlRenderer::effect(TVG_UNUSED RenderCompositor* cmp, TVG_UNUSED const RenderEffect* effect, TVG_UNUSED uint8_t opacity, TVG_UNUSED bool direct) { TVGLOG("GL_ENGINE", "SceneEffect(%d) is not supported", (int)effect->type); return false; diff --git a/src/renderer/gl_engine/tvgGlRenderer.h b/src/renderer/gl_engine/tvgGlRenderer.h index f814f1e0..a5f0b8c4 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.h +++ b/src/renderer/gl_engine/tvgGlRenderer.h @@ -87,7 +87,7 @@ public: bool endComposite(RenderCompositor* cmp) override; bool prepare(RenderEffect* effect) override; - bool effect(RenderCompositor* cmp, const RenderEffect* effect, bool direct) override; + bool effect(RenderCompositor* cmp, const RenderEffect* effect, uint8_t opacity, bool direct) override; static GlRenderer* gen(); static int init(TVG_UNUSED uint32_t threads); diff --git a/src/renderer/sw_engine/tvgSwCommon.h b/src/renderer/sw_engine/tvgSwCommon.h index f7cdf444..4ced7d5e 100644 --- a/src/renderer/sw_engine/tvgSwCommon.h +++ b/src/renderer/sw_engine/tvgSwCommon.h @@ -572,9 +572,9 @@ void rasterUnpremultiply(RenderSurface* surface); void rasterPremultiply(RenderSurface* surface); bool rasterConvertCS(RenderSurface* surface, ColorSpace to); -bool effectGaussianBlur(SwCompositor* cmp, SwSurface* surface, const RenderEffectGaussianBlur* params, bool direct); +bool effectGaussianBlur(SwCompositor* cmp, SwSurface* surface, const RenderEffectGaussianBlur* params); bool effectGaussianBlurPrepare(RenderEffectGaussianBlur* effect); -bool effectDropShadow(SwCompositor* cmp, SwSurface* surfaces[2], const RenderEffectDropShadow* params, bool direct); +bool effectDropShadow(SwCompositor* cmp, SwSurface* surfaces[2], const RenderEffectDropShadow* params, uint8_t opacity, bool direct); bool effectDropShadowPrepare(RenderEffectDropShadow* effect); #endif /* _TVG_SW_COMMON_H_ */ diff --git a/src/renderer/sw_engine/tvgSwPostEffect.cpp b/src/renderer/sw_engine/tvgSwPostEffect.cpp index 01e9e66d..4168917b 100644 --- a/src/renderer/sw_engine/tvgSwPostEffect.cpp +++ b/src/renderer/sw_engine/tvgSwPostEffect.cpp @@ -163,7 +163,7 @@ bool effectGaussianBlurPrepare(RenderEffectGaussianBlur* params) } -bool effectGaussianBlur(SwCompositor* cmp, SwSurface* surface, const RenderEffectGaussianBlur* params, TVG_UNUSED bool direct) +bool effectGaussianBlur(SwCompositor* cmp, SwSurface* surface, const RenderEffectGaussianBlur* params) { if (cmp->image.channelSize != sizeof(uint32_t)) { TVGERR("SW_ENGINE", "Not supported grayscale Gaussian Blur!"); @@ -237,7 +237,7 @@ static void _dropShadowFilter(uint32_t* dst, uint32_t* src, int stride, int w, i } auto iarr = 1.0f / (dimension + dimension + 1); - //#pragma omp parallel for + #pragma omp parallel for for (int y = 0; y < h; ++y) { auto p = y * stride; auto i = p; //current index @@ -335,7 +335,7 @@ bool effectDropShadowPrepare(RenderEffectDropShadow* params) //A quite same integration with effectGaussianBlur(). See it for detailed comments. //surface[0]: the original image, to overlay it into the filtered image. //surface[1]: temporary buffer for generating the filtered image. -bool effectDropShadow(SwCompositor* cmp, SwSurface* surface[2], const RenderEffectDropShadow* params, bool direct) +bool effectDropShadow(SwCompositor* cmp, SwSurface* surface[2], const RenderEffectDropShadow* params, uint8_t opacity, bool direct) { if (cmp->image.channelSize != sizeof(uint32_t)) { TVGERR("SW_ENGINE", "Not supported grayscale Drop Shadow!"); @@ -357,7 +357,7 @@ bool effectDropShadow(SwCompositor* cmp, SwSurface* surface[2], const RenderEffe auto stride = cmp->image.stride; auto front = cmp->image.buf32; auto back = buffer[1]->buf32; - auto opacity = params->color[3]; + opacity = MULTIPLY(params->color[3], opacity); TVGLOG("SW_ENGINE", "DropShadow region(%ld, %ld, %ld, %ld) params(%f %f %f), level(%d)", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y, params->angle, params->distance, params->sigma, data->level); diff --git a/src/renderer/sw_engine/tvgSwRenderer.cpp b/src/renderer/sw_engine/tvgSwRenderer.cpp index b6e8177a..001dc986 100644 --- a/src/renderer/sw_engine/tvgSwRenderer.cpp +++ b/src/renderer/sw_engine/tvgSwRenderer.cpp @@ -650,7 +650,7 @@ bool SwRenderer::prepare(RenderEffect* effect) } -bool SwRenderer::effect(RenderCompositor* cmp, const RenderEffect* effect, bool direct) +bool SwRenderer::effect(RenderCompositor* cmp, const RenderEffect* effect, uint8_t opacity, bool direct) { if (effect->invalid) return false; @@ -658,14 +658,14 @@ bool SwRenderer::effect(RenderCompositor* cmp, const RenderEffect* effect, bool switch (effect->type) { case SceneEffect::GaussianBlur: { - return effectGaussianBlur(p, request(surface->channelSize), static_cast(effect), direct); + return effectGaussianBlur(p, request(surface->channelSize), static_cast(effect)); } case SceneEffect::DropShadow: { auto cmp1 = request(surface->channelSize); cmp1->compositor->valid = false; auto cmp2 = request(surface->channelSize); SwSurface* surfaces[] = {cmp1, cmp2}; - auto ret = effectDropShadow(p, surfaces, static_cast(effect), direct); + auto ret = effectDropShadow(p, surfaces, static_cast(effect), opacity, direct); cmp1->compositor->valid = true; return ret; } diff --git a/src/renderer/sw_engine/tvgSwRenderer.h b/src/renderer/sw_engine/tvgSwRenderer.h index 489a024b..cc11f833 100644 --- a/src/renderer/sw_engine/tvgSwRenderer.h +++ b/src/renderer/sw_engine/tvgSwRenderer.h @@ -61,7 +61,7 @@ public: void clearCompositors(); bool prepare(RenderEffect* effect) override; - bool effect(RenderCompositor* cmp, const RenderEffect* effect, bool direct) override; + bool effect(RenderCompositor* cmp, const RenderEffect* effect, uint8_t opacity, bool direct) override; static SwRenderer* gen(); static bool init(uint32_t threads); diff --git a/src/renderer/tvgRender.h b/src/renderer/tvgRender.h index d73248fd..9bf37a03 100644 --- a/src/renderer/tvgRender.h +++ b/src/renderer/tvgRender.h @@ -343,7 +343,7 @@ public: virtual bool endComposite(RenderCompositor* cmp) = 0; virtual bool prepare(RenderEffect* effect) = 0; - virtual bool effect(RenderCompositor* cmp, const RenderEffect* effect, bool direct) = 0; + virtual bool effect(RenderCompositor* cmp, const RenderEffect* effect, uint8_t opacity, bool direct) = 0; }; static inline bool MASK_REGION_MERGING(MaskMethod method) diff --git a/src/renderer/tvgScene.h b/src/renderer/tvgScene.h index 371c807c..e742cb4b 100644 --- a/src/renderer/tvgScene.h +++ b/src/renderer/tvgScene.h @@ -142,7 +142,7 @@ struct Scene::Impl if (effects) { auto direct = effects->count == 1 ? true : false; for (auto e = effects->begin(); e < effects->end(); ++e) { - renderer->effect(cmp, *e, direct); + renderer->effect(cmp, *e, opacity, direct); } } renderer->endComposite(cmp); diff --git a/src/renderer/wg_engine/tvgWgRenderer.cpp b/src/renderer/wg_engine/tvgWgRenderer.cpp index c8e6342d..070904e3 100755 --- a/src/renderer/wg_engine/tvgWgRenderer.cpp +++ b/src/renderer/wg_engine/tvgWgRenderer.cpp @@ -469,7 +469,7 @@ bool WgRenderer::prepare(TVG_UNUSED RenderEffect* effect) } -bool WgRenderer::effect(TVG_UNUSED RenderCompositor* cmp, TVG_UNUSED const RenderEffect* effect, TVG_UNUSED bool direct) +bool WgRenderer::effect(TVG_UNUSED RenderCompositor* cmp, TVG_UNUSED const RenderEffect* effect, TVG_UNUSED uint8_t opacity, TVG_UNUSED bool direct) { TVGLOG("WG_ENGINE", "SceneEffect(%d) is not supported", (int)effect->type); return false; diff --git a/src/renderer/wg_engine/tvgWgRenderer.h b/src/renderer/wg_engine/tvgWgRenderer.h index 6bb37819..56e25457 100755 --- a/src/renderer/wg_engine/tvgWgRenderer.h +++ b/src/renderer/wg_engine/tvgWgRenderer.h @@ -52,7 +52,7 @@ public: bool endComposite(RenderCompositor* cmp) override; bool prepare(RenderEffect* effect) override; - bool effect(RenderCompositor* cmp, const RenderEffect* effect, bool direct) override; + bool effect(RenderCompositor* cmp, const RenderEffect* effect, uint8_t opacity, bool direct) override; static WgRenderer* gen(); static bool init(uint32_t threads);