diff --git a/src/renderer/gl_engine/tvgGlRenderer.cpp b/src/renderer/gl_engine/tvgGlRenderer.cpp index 29f75975..67671d5a 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.cpp +++ b/src/renderer/gl_engine/tvgGlRenderer.cpp @@ -946,14 +946,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 67a4a413..9fb0580e 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.h +++ b/src/renderer/gl_engine/tvgGlRenderer.h @@ -87,8 +87,9 @@ public: bool beginComposite(RenderCompositor* cmp, MaskMethod 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 0b1245ef..dce6606e 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 7cda2d06..836fd249 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 b8dc7cc1..45dd5500 100644 --- a/src/renderer/sw_engine/tvgSwRenderer.cpp +++ b/src/renderer/sw_engine/tvgSwRenderer.cpp @@ -660,23 +660,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 76d39363..62f3b28f 100644 --- a/src/renderer/sw_engine/tvgSwRenderer.h +++ b/src/renderer/sw_engine/tvgSwRenderer.h @@ -62,8 +62,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 a03b5ca1..37415ef0 100644 --- a/src/renderer/tvgRender.h +++ b/src/renderer/tvgRender.h @@ -406,8 +406,9 @@ public: virtual bool beginComposite(RenderCompositor* cmp, MaskMethod 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(MaskMethod method) diff --git a/src/renderer/tvgScene.h b/src/renderer/tvgScene.h index 92fe030a..8e9f979e 100644 --- a/src/renderer/tvgScene.h +++ b/src/renderer/tvgScene.h @@ -116,6 +116,12 @@ struct Scene::Impl : Paint::Impl paint->pImpl->update(renderer, transform, clips, opacity, flag, false); } + if (effects) { + ARRAY_FOREACH(p, *effects) { + renderer->prepare(*p, transform); + } + } + return nullptr; } @@ -141,7 +147,7 @@ struct Scene::Impl : Paint::Impl //Notify the possiblity of the direct composition of the effect result to the origin surface. auto direct = (effects->count == 1) & (compFlag == CompositionFlag::PostProcessing); ARRAY_FOREACH(p, *effects) { - renderer->effect(cmp, *p, direct); + if ((*p)->valid) renderer->render(cmp, *p, direct); } } renderer->endComposite(cmp); @@ -174,7 +180,7 @@ struct Scene::Impl : Paint::Impl if (effects) { ARRAY_FOREACH(p, *effects) { auto effect = *p; - 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 037ab196..78c09c2e 100755 --- a/src/renderer/wg_engine/tvgWgRenderer.cpp +++ b/src/renderer/wg_engine/tvgWgRenderer.cpp @@ -463,14 +463,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 e29f151f..ee00e780 100755 --- a/src/renderer/wg_engine/tvgWgRenderer.h +++ b/src/renderer/wg_engine/tvgWgRenderer.h @@ -53,8 +53,9 @@ public: bool beginComposite(RenderCompositor* cmp, MaskMethod 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);