mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
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:
parent
6c0c8865cd
commit
819b93a9a4
10 changed files with 110 additions and 74 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue