From 819b93a9a49658640cf08bf9f44e01b69224c646 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 17 Jan 2025 15:05:42 +0900 Subject: [PATCH] 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 --- src/renderer/gl_engine/tvgGlRenderer.cpp | 10 ++- src/renderer/gl_engine/tvgGlRenderer.h | 5 +- src/renderer/sw_engine/tvgSwCommon.h | 12 +-- src/renderer/sw_engine/tvgSwPostEffect.cpp | 96 +++++++++++----------- src/renderer/sw_engine/tvgSwRenderer.cpp | 26 ++++-- src/renderer/sw_engine/tvgSwRenderer.h | 5 +- src/renderer/tvgRender.h | 5 +- src/renderer/tvgScene.h | 10 ++- src/renderer/wg_engine/tvgWgRenderer.cpp | 10 ++- src/renderer/wg_engine/tvgWgRenderer.h | 5 +- 10 files changed, 110 insertions(+), 74 deletions(-) diff --git a/src/renderer/gl_engine/tvgGlRenderer.cpp b/src/renderer/gl_engine/tvgGlRenderer.cpp index 63d38883..cc0324bb 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.cpp +++ b/src/renderer/gl_engine/tvgGlRenderer.cpp @@ -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; diff --git a/src/renderer/gl_engine/tvgGlRenderer.h b/src/renderer/gl_engine/tvgGlRenderer.h index d88b4c9c..842b4ced 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.h +++ b/src/renderer/gl_engine/tvgGlRenderer.h @@ -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); diff --git a/src/renderer/sw_engine/tvgSwCommon.h b/src/renderer/sw_engine/tvgSwCommon.h index 1b209b4e..a45a996a 100644 --- a/src/renderer/sw_engine/tvgSwCommon.h +++ b/src/renderer/sw_engine/tvgSwCommon.h @@ -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_ */ diff --git a/src/renderer/sw_engine/tvgSwPostEffect.cpp b/src/renderer/sw_engine/tvgSwPostEffect.cpp index 052468f0..329e1214 100644 --- a/src/renderer/sw_engine/tvgSwPostEffect.cpp +++ b/src/renderer/sw_engine/tvgSwPostEffect.cpp @@ -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(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(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(params->rd)->offset; + auto extra = static_cast(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(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; } diff --git a/src/renderer/sw_engine/tvgSwRenderer.cpp b/src/renderer/sw_engine/tvgSwRenderer.cpp index 47dc6596..5b9719d2 100644 --- a/src/renderer/sw_engine/tvgSwRenderer.cpp +++ b/src/renderer/sw_engine/tvgSwRenderer.cpp @@ -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(effect)); - case SceneEffect::DropShadow: return effectDropShadowPrepare(static_cast(effect)); - case SceneEffect::Fill: return effectFillPrepare(static_cast(effect)); - case SceneEffect::Tint: return effectTintPrepare(static_cast(effect)); - case SceneEffect::Tritone: return effectTritonePrepare(static_cast(effect)); + case SceneEffect::GaussianBlur: effectGaussianBlurUpdate(static_cast(effect), transform); break; + case SceneEffect::DropShadow: effectDropShadowUpdate(static_cast(effect), transform); break; + case SceneEffect::Fill: effectFillUpdate(static_cast(effect)); break; + case SceneEffect::Tint: effectTintUpdate(static_cast(effect)); break; + case SceneEffect::Tritone: effectTritoneUpdate(static_cast(effect)); break; + default: break; + } +} + + +bool SwRenderer::region(RenderEffect* effect) +{ + switch (effect->type) { + case SceneEffect::GaussianBlur: return effectGaussianBlurRegion(static_cast(effect)); + case SceneEffect::DropShadow: return effectDropShadowRegion(static_cast(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(cmp); if (p->image.channelSize != sizeof(uint32_t)) { diff --git a/src/renderer/sw_engine/tvgSwRenderer.h b/src/renderer/sw_engine/tvgSwRenderer.h index 02fbe3b6..27868abf 100644 --- a/src/renderer/sw_engine/tvgSwRenderer.h +++ b/src/renderer/sw_engine/tvgSwRenderer.h @@ -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); diff --git a/src/renderer/tvgRender.h b/src/renderer/tvgRender.h index 2a896520..7d432cac 100644 --- a/src/renderer/tvgRender.h +++ b/src/renderer/tvgRender.h @@ -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) diff --git a/src/renderer/tvgScene.h b/src/renderer/tvgScene.h index bc789584..e2eba0ce 100644 --- a/src/renderer/tvgScene.h +++ b/src/renderer/tvgScene.h @@ -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); diff --git a/src/renderer/wg_engine/tvgWgRenderer.cpp b/src/renderer/wg_engine/tvgWgRenderer.cpp index 38aaadd9..10d5453f 100755 --- a/src/renderer/wg_engine/tvgWgRenderer.cpp +++ b/src/renderer/wg_engine/tvgWgRenderer.cpp @@ -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; diff --git a/src/renderer/wg_engine/tvgWgRenderer.h b/src/renderer/wg_engine/tvgWgRenderer.h index 4c90b6fc..f255d350 100755 --- a/src/renderer/wg_engine/tvgWgRenderer.h +++ b/src/renderer/wg_engine/tvgWgRenderer.h @@ -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);