From 527b1af926285a4271003f673f99a175c0e621a6 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 1 May 2023 22:42:41 +0900 Subject: [PATCH] common sw_engine: applied colorspace format size. Now backend engines know which channel size is required for compositions. @Issue: https://github.com/thorvg/thorvg/issues/976 --- src/lib/gl_engine/tvgGlRenderer.cpp | 2 +- src/lib/gl_engine/tvgGlRenderer.h | 2 +- src/lib/sw_engine/tvgSwCommon.h | 1 + src/lib/sw_engine/tvgSwRenderer.cpp | 16 +++++++---- src/lib/sw_engine/tvgSwRenderer.h | 2 +- src/lib/tvgPaint.cpp | 3 +- src/lib/tvgRender.h | 34 ++++++++++++++++++++++- src/lib/tvgSceneImpl.h | 2 +- src/loaders/external_jpg/tvgJpgLoader.cpp | 1 + src/loaders/external_png/tvgPngLoader.cpp | 1 + src/loaders/jpg/tvgJpgLoader.cpp | 1 + src/loaders/png/tvgPngLoader.cpp | 1 + src/loaders/raw/tvgRawLoader.cpp | 1 + 13 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/lib/gl_engine/tvgGlRenderer.cpp b/src/lib/gl_engine/tvgGlRenderer.cpp index b18189fe..d7ea63bf 100644 --- a/src/lib/gl_engine/tvgGlRenderer.cpp +++ b/src/lib/gl_engine/tvgGlRenderer.cpp @@ -102,7 +102,7 @@ bool GlRenderer::postRender() } -Compositor* GlRenderer::target(TVG_UNUSED const RenderRegion& region) +Compositor* GlRenderer::target(TVG_UNUSED const RenderRegion& region, TVG_UNUSED ColorSpace cs) { //TODO: Prepare frameBuffer & Setup render target for composition return nullptr; diff --git a/src/lib/gl_engine/tvgGlRenderer.h b/src/lib/gl_engine/tvgGlRenderer.h index d20b3ead..b8038549 100644 --- a/src/lib/gl_engine/tvgGlRenderer.h +++ b/src/lib/gl_engine/tvgGlRenderer.h @@ -47,7 +47,7 @@ public: bool sync() override; bool clear() override; - Compositor* target(const RenderRegion& region) override; + Compositor* target(const RenderRegion& region, ColorSpace cs) override; bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) override; bool endComposite(Compositor* cmp) override; diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 04b56ffd..79e30d82 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -228,6 +228,7 @@ struct SwImage int32_t ox = 0; //offset x int32_t oy = 0; //offset y float scale; + uint8_t channelSize; bool direct = false; //draw image directly (with offset) bool scaled = false; //draw scaled image diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 95e347b9..4bf399b7 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -289,6 +289,7 @@ struct SwImageTask : SwTask image.w = source->w; image.h = source->h; image.stride = source->stride; + image.channelSize = source->channelSize; //Invisible shape turned to visible by alpha. if ((flags & (RenderUpdateFlag::Image | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) && (opacity > 0)) { @@ -434,6 +435,7 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t surface->w = w; surface->h = h; surface->cs = cs; + surface->channelSize = CHANNEL_SIZE(cs); surface->premultiplied = true; surface->owner = true; @@ -505,7 +507,7 @@ bool SwRenderer::renderShape(RenderData data) //Do Stroking Composition if (task->cmpStroking) { opacity = 255; - cmp = target(task->bounds()); + cmp = target(task->bounds(), colorSpace()); beginComposite(cmp, CompositeMethod::None, task->opacity); //No Stroking Composition } else { @@ -571,7 +573,7 @@ bool SwRenderer::mempool(bool shared) } -Compositor* SwRenderer::target(const RenderRegion& region) +Compositor* SwRenderer::target(const RenderRegion& region, ColorSpace cs) { auto x = region.x; auto y = region.y; @@ -585,9 +587,11 @@ Compositor* SwRenderer::target(const RenderRegion& region) SwSurface* cmp = nullptr; + auto reqChannelSize = CHANNEL_SIZE(cs); + //Use cached data for (auto p = compositors.data; p < (compositors.data + compositors.count); ++p) { - if ((*p)->compositor->valid) { + if ((*p)->compositor->valid && (*p)->compositor->image.channelSize == reqChannelSize) { cmp = *p; break; } @@ -602,8 +606,10 @@ Compositor* SwRenderer::target(const RenderRegion& region) cmp->compositor = new SwCompositor; - //SwImage, Optimize Me: Surface size from MainSurface(WxH) to Parameter W x H - cmp->compositor->image.data = (uint32_t*) malloc(sizeof(uint32_t) * surface->stride * surface->h); + //TODO: We can optimize compositor surface size from (surface->stride x surface->h) to Parameter(w x h) + cmp->compositor->image.data = (uint32_t*) malloc(reqChannelSize * surface->stride * surface->h); + cmp->channelSize = cmp->compositor->image.channelSize = reqChannelSize; + compositors.push(cmp); } diff --git a/src/lib/sw_engine/tvgSwRenderer.h b/src/lib/sw_engine/tvgSwRenderer.h index 0ab185bc..785e4638 100644 --- a/src/lib/sw_engine/tvgSwRenderer.h +++ b/src/lib/sw_engine/tvgSwRenderer.h @@ -54,7 +54,7 @@ public: bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, ColorSpace cs); bool mempool(bool shared); - Compositor* target(const RenderRegion& region) override; + Compositor* target(const RenderRegion& region, ColorSpace cs) override; bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) override; bool endComposite(Compositor* cmp) override; void clearCompositors(); diff --git a/src/lib/tvgPaint.cpp b/src/lib/tvgPaint.cpp index 1ea1697b..6d406af0 100644 --- a/src/lib/tvgPaint.cpp +++ b/src/lib/tvgPaint.cpp @@ -167,7 +167,8 @@ bool Paint::Impl::render(RenderMethod& renderer) if (compData && compData->method != CompositeMethod::ClipPath && !(compData->target->pImpl->ctxFlag & ContextFlag::FastTrack)) { auto region = smethod->bounds(renderer); if (region.w == 0 || region.h == 0) return true; - cmp = renderer.target(region); + //cmp = renderer.target(region, COMPOSITE_TO_COLORSPACE(renderer, compData->method)); + cmp = renderer.target(region, renderer.colorSpace()); if (renderer.beginComposite(cmp, CompositeMethod::None, 255)) { compData->target->pImpl->render(renderer); } diff --git a/src/lib/tvgRender.h b/src/lib/tvgRender.h index 1a8472d0..90eaaf0f 100644 --- a/src/lib/tvgRender.h +++ b/src/lib/tvgRender.h @@ -51,6 +51,7 @@ struct Surface uint32_t stride; uint32_t w, h; ColorSpace cs; + uint8_t channelSize; bool premultiplied; //Alpha-premultiplied bool owner; //Only owner could modify the buffer @@ -227,11 +228,42 @@ public: virtual bool clear() = 0; virtual bool sync() = 0; - virtual Compositor* target(const RenderRegion& region) = 0; + virtual Compositor* target(const RenderRegion& region, ColorSpace cs) = 0; virtual bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) = 0; virtual bool endComposite(Compositor* cmp) = 0; }; +static inline uint8_t CHANNEL_SIZE(ColorSpace cs) +{ + switch(cs) { + case ColorSpace::ABGR8888: + case ColorSpace::ABGR8888S: + case ColorSpace::ARGB8888: + case ColorSpace::ARGB8888S: + return sizeof(uint32_t); + case ColorSpace::Grayscale8: + return sizeof(uint8_t); + case ColorSpace::Unsupported: + default: + TVGERR("SW_ENGINE", "Unsupported Channel Size! = %d", (int)cs); + return 0; + } +} + +static inline ColorSpace COMPOSITE_TO_COLORSPACE(RenderMethod& renderer, CompositeMethod method) +{ + switch(method) { + case CompositeMethod::AlphaMask: + case CompositeMethod::InvAlphaMask: + return ColorSpace::Grayscale8; + case CompositeMethod::LumaMask: + return renderer.colorSpace(); + default: + TVGERR("COMMON", "Unsupported Composite Size! = %d", (int)method); + return ColorSpace::Unsupported; + } +} + } #endif //_TVG_RENDER_H_ diff --git a/src/lib/tvgSceneImpl.h b/src/lib/tvgSceneImpl.h index 5766b9e7..9ce4d0b3 100644 --- a/src/lib/tvgSceneImpl.h +++ b/src/lib/tvgSceneImpl.h @@ -135,7 +135,7 @@ struct Scene::Impl Compositor* cmp = nullptr; if (needComposition(opacity)) { - cmp = renderer.target(bounds(renderer)); + cmp = renderer.target(bounds(renderer), renderer.colorSpace()); renderer.beginComposite(cmp, CompositeMethod::None, opacity); } diff --git a/src/loaders/external_jpg/tvgJpgLoader.cpp b/src/loaders/external_jpg/tvgJpgLoader.cpp index 1c47b4f5..88c80519 100644 --- a/src/loaders/external_jpg/tvgJpgLoader.cpp +++ b/src/loaders/external_jpg/tvgJpgLoader.cpp @@ -165,6 +165,7 @@ unique_ptr JpgLoader::bitmap() surface->w = w; surface->h = h; surface->cs = cs; + surface->channelSize = sizeof(uint32_t); surface->premultiplied = true; surface->owner = true; diff --git a/src/loaders/external_png/tvgPngLoader.cpp b/src/loaders/external_png/tvgPngLoader.cpp index 1dc4905e..3c0a9688 100644 --- a/src/loaders/external_png/tvgPngLoader.cpp +++ b/src/loaders/external_png/tvgPngLoader.cpp @@ -111,6 +111,7 @@ unique_ptr PngLoader::bitmap() surface->w = w; surface->h = h; surface->cs = cs; + surface->channelSize = sizeof(uint32_t); surface->owner = true; surface->premultiplied = false; diff --git a/src/loaders/jpg/tvgJpgLoader.cpp b/src/loaders/jpg/tvgJpgLoader.cpp index 15f4cc9b..2c371d5b 100644 --- a/src/loaders/jpg/tvgJpgLoader.cpp +++ b/src/loaders/jpg/tvgJpgLoader.cpp @@ -125,6 +125,7 @@ unique_ptr JpgLoader::bitmap() surface->w = static_cast(w); surface->h = static_cast(h); surface->cs = cs; + surface->channelSize = sizeof(uint32_t); surface->premultiplied = true; surface->owner = true; diff --git a/src/loaders/png/tvgPngLoader.cpp b/src/loaders/png/tvgPngLoader.cpp index b4364ec8..85ff433b 100644 --- a/src/loaders/png/tvgPngLoader.cpp +++ b/src/loaders/png/tvgPngLoader.cpp @@ -161,6 +161,7 @@ unique_ptr PngLoader::bitmap() surface->w = static_cast(w); surface->h = static_cast(h); surface->cs = cs; + surface->channelSize = sizeof(uint32_t); surface->premultiplied = false; surface->owner = true; diff --git a/src/loaders/raw/tvgRawLoader.cpp b/src/loaders/raw/tvgRawLoader.cpp index d81de06c..16feb0ff 100644 --- a/src/loaders/raw/tvgRawLoader.cpp +++ b/src/loaders/raw/tvgRawLoader.cpp @@ -87,6 +87,7 @@ unique_ptr RawLoader::bitmap() surface->w = static_cast(w); surface->h = static_cast(h); surface->cs = cs; + surface->channelSize = sizeof(uint32_t); surface->premultiplied = true; surface->owner = true;