renderer: improved engine for scalable effects

RenderMethod effects methods would have changes:
 + update()               //update the effects if any
 - prepare() -> region()  //update the effect drawing region
 - effect() -> render()   //draw the effect
This commit is contained in:
Hermet Park 2025-01-17 15:05:42 +09:00
parent 6c0c8865cd
commit 819b93a9a4
10 changed files with 110 additions and 74 deletions

View file

@ -1072,14 +1072,20 @@ bool GlRenderer::endComposite(RenderCompositor* cmp)
}
bool GlRenderer::prepare(TVG_UNUSED RenderEffect* effect)
void GlRenderer::prepare(TVG_UNUSED RenderEffect* effect, TVG_UNUSED const Matrix& transform)
{
//TODO: prepare the effect
}
bool GlRenderer::region(TVG_UNUSED RenderEffect* effect)
{
//TODO: Return if the current post effect requires the region expansion
return false;
}
bool GlRenderer::effect(TVG_UNUSED RenderCompositor* cmp, TVG_UNUSED const RenderEffect* effect, TVG_UNUSED bool direct)
bool GlRenderer::render(TVG_UNUSED RenderCompositor* cmp, TVG_UNUSED const RenderEffect* effect, TVG_UNUSED bool direct)
{
TVGLOG("GL_ENGINE", "SceneEffect(%d) is not supported", (int)effect->type);
return false;

View file

@ -86,8 +86,9 @@ public:
bool beginComposite(RenderCompositor* cmp, CompositeMethod method, uint8_t opacity) override;
bool endComposite(RenderCompositor* cmp) override;
bool prepare(RenderEffect* effect) override;
bool effect(RenderCompositor* cmp, const RenderEffect* effect, bool direct) override;
void prepare(RenderEffect* effect, const Matrix& transform) override;
bool region(RenderEffect* effect) override;
bool render(RenderCompositor* cmp, const RenderEffect* effect, bool direct) override;
static GlRenderer* gen();
static int init(TVG_UNUSED uint32_t threads);

View file

@ -584,14 +584,16 @@ bool rasterConvertCS(RenderSurface* surface, ColorSpace to);
uint32_t rasterUnpremultiply(uint32_t data);
bool effectGaussianBlur(SwCompositor* cmp, SwSurface* surface, const RenderEffectGaussianBlur* params);
bool effectGaussianBlurPrepare(RenderEffectGaussianBlur* effect);
bool effectGaussianBlurRegion(RenderEffectGaussianBlur* effect);
void effectGaussianBlurUpdate(RenderEffectGaussianBlur* effect, const Matrix& transform);
bool effectDropShadow(SwCompositor* cmp, SwSurface* surfaces[2], const RenderEffectDropShadow* params, bool direct);
bool effectDropShadowPrepare(RenderEffectDropShadow* effect);
bool effectFillPrepare(RenderEffectFill* effect);
bool effectDropShadowRegion(RenderEffectDropShadow* effect);
void effectDropShadowUpdate(RenderEffectDropShadow* effect, const Matrix& transform);
void effectFillUpdate(RenderEffectFill* effect);
bool effectFill(SwCompositor* cmp, const RenderEffectFill* params, bool direct);
bool effectTintPrepare(RenderEffectTint* effect);
void effectTintUpdate(RenderEffectTint* effect);
bool effectTint(SwCompositor* cmp, const RenderEffectTint* params, bool direct);
bool effectTritonePrepare(RenderEffectTritone* effect);
void effectTritoneUpdate(RenderEffectTritone* effect);
bool effectTritone(SwCompositor* cmp, const RenderEffectTritone* params, bool direct);
#endif /* _TVG_SW_COMMON_H_ */

View file

@ -32,23 +32,10 @@ struct SwGaussianBlur
static constexpr int MAX_LEVEL = 3;
int level;
int kernel[MAX_LEVEL];
int extends;
};
static void _gaussianExtendRegion(RenderRegion& region, int extra, int8_t direction)
{
//bbox region expansion for feathering
if (direction != 2) {
region.x = -extra;
region.w = extra * 2;
}
if (direction != 1) {
region.y = -extra;
region.h = extra * 2;
}
}
static int _gaussianEdgeWrap(int end, int idx)
{
auto r = idx % end;
@ -142,27 +129,44 @@ static int _gaussianInit(SwGaussianBlur* data, float sigma, int quality)
}
bool effectGaussianBlurPrepare(RenderEffectGaussianBlur* params)
bool effectGaussianBlurRegion(RenderEffectGaussianBlur* params)
{
auto rd = (SwGaussianBlur*)malloc(sizeof(SwGaussianBlur));
//bbox region expansion for feathering
auto& region = params->extend;
auto extra = static_cast<SwGaussianBlur*>(params->rd)->extends;
auto extends = _gaussianInit(rd, params->sigma * params->sigma, params->quality);
//invalid
if (extends == 0) {
free(rd);
return false;
if (params->direction != 2) {
region.x = -extra;
region.w = extra * 2;
}
if (params->direction != 1) {
region.y = -extra;
region.h = extra * 2;
}
_gaussianExtendRegion(params->extend, extends, params->direction);
params->rd = rd;
params->valid = true;
return true;
}
void effectGaussianBlurUpdate(RenderEffectGaussianBlur* params, const Matrix& transform)
{
if (!params->rd) params->rd = (SwGaussianBlur*)malloc(sizeof(SwGaussianBlur));
auto rd = static_cast<SwGaussianBlur*>(params->rd);
//compute box kernel sizes
auto scale = sqrt(transform.e11 * transform.e11 + transform.e12 * transform.e12);
rd->extends = _gaussianInit(rd, std::pow(params->sigma * scale, 2), params->quality);
//invalid
if (rd->extends == 0) {
params->valid = false;
return;
}
params->valid = true;
}
bool effectGaussianBlur(SwCompositor* cmp, SwSurface* surface, const RenderEffectGaussianBlur* params)
{
auto& buffer = surface->compositor->image;
@ -281,9 +285,13 @@ static void _dropShadowShift(uint32_t* dst, uint32_t* src, int stride, SwBBox& r
}
static void _dropShadowExtendRegion(RenderRegion& region, int extra, SwPoint& offset)
bool effectDropShadowRegion(RenderEffectDropShadow* params)
{
//bbox region expansion for feathering
auto& region = params->extend;
auto& offset = static_cast<SwDropShadow*>(params->rd)->offset;
auto extra = static_cast<SwDropShadow*>(params->rd)->extends;
region.x = -extra;
region.w = extra * 2;
region.y = -extra;
@ -293,20 +301,24 @@ static void _dropShadowExtendRegion(RenderRegion& region, int extra, SwPoint& of
region.y = std::min(region.y + (int32_t)offset.y, region.y);
region.w += abs(offset.x);
region.h += abs(offset.y);
return true;
}
bool effectDropShadowPrepare(RenderEffectDropShadow* params)
void effectDropShadowUpdate(RenderEffectDropShadow* params, const Matrix& transform)
{
auto rd = (SwDropShadow*)malloc(sizeof(SwDropShadow));
if (!params->rd) params->rd = (SwDropShadow*)malloc(sizeof(SwDropShadow));
auto rd = static_cast<SwDropShadow*>(params->rd);
//compute box kernel sizes
auto extends = _gaussianInit(rd, params->sigma * params->sigma, params->quality);
auto scale = sqrt(transform.e11 * transform.e11 + transform.e12 * transform.e12);
rd->extends = _gaussianInit(rd, std::pow(params->sigma * scale, 2), params->quality);
//invalid
if (extends == 0 || params->color[3] == 0) {
free(rd);
return false;
if (rd->extends == 0 || params->color[3] == 0) {
params->valid = false;
return;
}
//offset
@ -317,13 +329,7 @@ bool effectDropShadowPrepare(RenderEffectDropShadow* params)
rd->offset = {0, 0};
}
//bbox region expansion for feathering
_dropShadowExtendRegion(params->extend, extends, rd->offset);
params->rd = rd;
params->valid = true;
return true;
}
@ -405,10 +411,9 @@ bool effectDropShadow(SwCompositor* cmp, SwSurface* surface[2], const RenderEffe
/* Fill Implementation */
/************************************************************************/
bool effectFillPrepare(RenderEffectFill* params)
void effectFillUpdate(RenderEffectFill* params)
{
params->valid = true;
return true;
}
@ -456,10 +461,9 @@ bool effectFill(SwCompositor* cmp, const RenderEffectFill* params, bool direct)
/* Tint Implementation */
/************************************************************************/
bool effectTintPrepare(RenderEffectTint* params)
void effectTintUpdate(RenderEffectTint* params)
{
params->valid = true;
return true;
}
@ -529,10 +533,10 @@ static uint32_t _trintone(uint32_t s, uint32_t m, uint32_t h, int l)
}
}
bool effectTritonePrepare(RenderEffectTritone* params)
void effectTritoneUpdate(RenderEffectTritone* params)
{
params->valid = true;
return true;
}

View file

@ -655,23 +655,31 @@ bool SwRenderer::endComposite(RenderCompositor* cmp)
}
bool SwRenderer::prepare(RenderEffect* effect)
void SwRenderer::prepare(RenderEffect* effect, const Matrix& transform)
{
switch (effect->type) {
case SceneEffect::GaussianBlur: return effectGaussianBlurPrepare(static_cast<RenderEffectGaussianBlur*>(effect));
case SceneEffect::DropShadow: return effectDropShadowPrepare(static_cast<RenderEffectDropShadow*>(effect));
case SceneEffect::Fill: return effectFillPrepare(static_cast<RenderEffectFill*>(effect));
case SceneEffect::Tint: return effectTintPrepare(static_cast<RenderEffectTint*>(effect));
case SceneEffect::Tritone: return effectTritonePrepare(static_cast<RenderEffectTritone*>(effect));
case SceneEffect::GaussianBlur: effectGaussianBlurUpdate(static_cast<RenderEffectGaussianBlur*>(effect), transform); break;
case SceneEffect::DropShadow: effectDropShadowUpdate(static_cast<RenderEffectDropShadow*>(effect), transform); break;
case SceneEffect::Fill: effectFillUpdate(static_cast<RenderEffectFill*>(effect)); break;
case SceneEffect::Tint: effectTintUpdate(static_cast<RenderEffectTint*>(effect)); break;
case SceneEffect::Tritone: effectTritoneUpdate(static_cast<RenderEffectTritone*>(effect)); break;
default: break;
}
}
bool SwRenderer::region(RenderEffect* effect)
{
switch (effect->type) {
case SceneEffect::GaussianBlur: return effectGaussianBlurRegion(static_cast<RenderEffectGaussianBlur*>(effect));
case SceneEffect::DropShadow: return effectDropShadowRegion(static_cast<RenderEffectDropShadow*>(effect));
default: return false;
}
}
bool SwRenderer::effect(RenderCompositor* cmp, const RenderEffect* effect, bool direct)
bool SwRenderer::render(RenderCompositor* cmp, const RenderEffect* effect, bool direct)
{
if (!effect->valid) return false;
auto p = static_cast<SwCompositor*>(cmp);
if (p->image.channelSize != sizeof(uint32_t)) {

View file

@ -60,8 +60,9 @@ public:
bool endComposite(RenderCompositor* cmp) override;
void clearCompositors();
bool prepare(RenderEffect* effect) override;
bool effect(RenderCompositor* cmp, const RenderEffect* effect, bool direct) override;
void prepare(RenderEffect* effect, const Matrix& transform) override;
bool region(RenderEffect* effect) override;
bool render(RenderCompositor* cmp, const RenderEffect* effect, bool direct) override;
static SwRenderer* gen();
static bool init(uint32_t threads);

View file

@ -413,8 +413,9 @@ public:
virtual bool beginComposite(RenderCompositor* cmp, CompositeMethod method, uint8_t opacity) = 0;
virtual bool endComposite(RenderCompositor* cmp) = 0;
virtual bool prepare(RenderEffect* effect) = 0;
virtual bool effect(RenderCompositor* cmp, const RenderEffect* effect, bool direct) = 0;
virtual void prepare(RenderEffect* effect, const Matrix& transform) = 0;
virtual bool region(RenderEffect* effect) = 0;
virtual bool render(RenderCompositor* cmp, const RenderEffect* effect, bool direct) = 0;
};
static inline bool MASK_REGION_MERGING(CompositeMethod method)

View file

@ -121,6 +121,12 @@ struct Scene::Impl
paint->pImpl->update(renderer, transform, clips, opacity, flag, false);
}
if (effects) {
for (auto e = effects->begin(); e < effects->end(); ++e) {
renderer->prepare(*e, transform);
}
}
return nullptr;
}
@ -146,7 +152,7 @@ struct Scene::Impl
//Notify the possiblity of the direct composition of the effect result to the origin surface.
auto direct = (effects->count == 1) & (compFlag == CompositionFlag::PostProcessing);
for (auto e = effects->begin(); e < effects->end(); ++e) {
renderer->effect(cmp, *e, direct);
if ((*e)->valid) renderer->render(cmp, *e, direct);
}
}
renderer->endComposite(cmp);
@ -179,7 +185,7 @@ struct Scene::Impl
if (effects) {
for (auto e = effects->begin(); e < effects->end(); ++e) {
auto effect = *e;
if (effect->valid || renderer->prepare(effect)) {
if (effect->valid && renderer->region(effect)) {
ex = std::min(ex, effect->extend.x);
ey = std::min(ey, effect->extend.y);
ew = std::max(ew, effect->extend.w);

View file

@ -424,14 +424,20 @@ bool WgRenderer::endComposite(RenderCompositor* cmp)
}
bool WgRenderer::prepare(TVG_UNUSED RenderEffect* effect)
void WgRenderer::prepare(TVG_UNUSED RenderEffect* effect, TVG_UNUSED const Matrix& transform)
{
//TODO: prepare the effect
}
bool WgRenderer::region(TVG_UNUSED RenderEffect* effect)
{
//TODO: Return if the current post effect requires the region expansion
return false;
}
bool WgRenderer::effect(TVG_UNUSED RenderCompositor* cmp, TVG_UNUSED const RenderEffect* effect, TVG_UNUSED bool direct)
bool WgRenderer::render(TVG_UNUSED RenderCompositor* cmp, TVG_UNUSED const RenderEffect* effect, TVG_UNUSED bool direct)
{
TVGLOG("WG_ENGINE", "SceneEffect(%d) is not supported", (int)effect->type);
return false;

View file

@ -52,8 +52,9 @@ public:
bool beginComposite(RenderCompositor* cmp, CompositeMethod method, uint8_t opacity) override;
bool endComposite(RenderCompositor* cmp) override;
bool prepare(RenderEffect* effect) override;
bool effect(RenderCompositor* cmp, const RenderEffect* effect, bool direct) override;
void prepare(TVG_UNUSED RenderEffect* effect, TVG_UNUSED const Matrix& transform) override;
bool region(RenderEffect* effect) override;
bool render(RenderCompositor* cmp, const RenderEffect* effect, bool direct) override;
static WgRenderer* gen();
static bool init(uint32_t threads);