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.
This commit is contained in:
Hermet Park 2024-11-23 00:52:06 +09:00 committed by Hermet Park
parent 077a0481c4
commit 877c524e5e
10 changed files with 16 additions and 16 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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_ */

View file

@ -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);

View file

@ -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<const RenderEffectGaussianBlur*>(effect), direct);
return effectGaussianBlur(p, request(surface->channelSize), static_cast<const RenderEffectGaussianBlur*>(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<const RenderEffectDropShadow*>(effect), direct);
auto ret = effectDropShadow(p, surfaces, static_cast<const RenderEffectDropShadow*>(effect), opacity, direct);
cmp1->compositor->valid = true;
return ret;
}

View file

@ -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);

View file

@ -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)

View file

@ -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);

View file

@ -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;

View file

@ -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);