diff --git a/src/lib/gl_engine/tvgGlRenderer.cpp b/src/lib/gl_engine/tvgGlRenderer.cpp index da306c96..a005b747 100644 --- a/src/lib/gl_engine/tvgGlRenderer.cpp +++ b/src/lib/gl_engine/tvgGlRenderer.cpp @@ -189,7 +189,7 @@ bool GlRenderer::dispose(RenderData data) } -RenderData GlRenderer::prepare(TVG_UNUSED Surface* image, TVG_UNUSED const RenderMesh* mesh, TVG_UNUSED RenderData data, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED uint32_t opacity, TVG_UNUSED Array& clips, TVG_UNUSED RenderUpdateFlag flags) +RenderData GlRenderer::prepare(TVG_UNUSED Surface* surface, TVG_UNUSED const RenderMesh* mesh, TVG_UNUSED RenderData data, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED uint32_t opacity, TVG_UNUSED Array& clips, TVG_UNUSED RenderUpdateFlag flags) { //TODO: return nullptr; diff --git a/src/lib/gl_engine/tvgGlRenderer.h b/src/lib/gl_engine/tvgGlRenderer.h index 30d050fa..1411a177 100644 --- a/src/lib/gl_engine/tvgGlRenderer.h +++ b/src/lib/gl_engine/tvgGlRenderer.h @@ -32,7 +32,7 @@ public: RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags, bool clipper) override; RenderData prepare(const Array& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) override; - RenderData prepare(Surface* image, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) override; + RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) override; bool preRender() override; bool renderShape(RenderData data) override; bool renderImage(RenderData data) override; diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 3e26990a..49cf9deb 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -359,5 +359,6 @@ bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id); bool rasterClear(SwSurface* surface); void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len); void rasterUnpremultiply(SwSurface* surface); +bool rasterConvertCS(Surface* surface, ColorSpace to); #endif /* _TVG_SW_COMMON_H_ */ diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 1b9f77a5..a4bf8c4d 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -1572,4 +1572,22 @@ bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, con //TODO: case: _rasterAlphaImageMesh() if (mesh && mesh->triangleCnt > 0) return _transformedRGBAImageMesh(surface, image, mesh, transform, &bbox, opacity); else return _rasterRGBAImage(surface, image, transform, bbox, opacity); +} + + +bool rasterConvertCS(Surface* surface, ColorSpace to) +{ + //TOOD: Support SIMD accelerations + auto from = surface->cs; + + if ((from == ColorSpace::ABGR8888 && to == ColorSpace::ARGB8888) || (from == ColorSpace::ABGR8888S && to == ColorSpace::ARGB8888S)) { + return cRasterABGRtoARGB(surface); + } + if ((from == ColorSpace::ARGB8888 && to == ColorSpace::ABGR8888) || (from == ColorSpace::ARGB8888S && to == ColorSpace::ABGR8888S)) { + return cRasterARGBtoABGR(surface); + } + + surface->cs = to; + + return false; } \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwRasterC.h b/src/lib/sw_engine/tvgSwRasterC.h index 18118aae..d45d68c6 100644 --- a/src/lib/sw_engine/tvgSwRasterC.h +++ b/src/lib/sw_engine/tvgSwRasterC.h @@ -61,3 +61,27 @@ static bool inline cRasterTranslucentRect(SwSurface* surface, const SwBBox& regi } return true; } + + +static bool inline cRasterABGRtoARGB(Surface* surface) +{ + TVGLOG("SW_ENGINE", "Convert ColorSpace ABGR - ARGB"); + + auto buffer = surface->buffer; + for (uint32_t y = 0; y < surface->h; ++y, buffer += surface->stride) { + auto dst = buffer; + for (uint32_t x = 0; x < surface->w; ++x, ++dst) { + auto c = *dst; + //flip Blue, Red channels + *dst = (c & 0xff000000) + ((c & 0x00ff0000) >> 16) + (c & 0x0000ff00) + ((c & 0x000000ff) << 16); + } + } + return true; +} + + +static bool inline cRasterARGBtoABGR(Surface* surface) +{ + //exactly same with ABGRtoARGB + return cRasterABGRtoARGB(surface); +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 0909d304..0ae58521 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -258,6 +258,7 @@ struct SwSceneTask : SwTask struct SwImageTask : SwTask { SwImage image; + Surface* source; //Image source const RenderMesh* mesh = nullptr; //Should be valid ptr in action bool clip(SwRleData* target) override @@ -276,6 +277,14 @@ struct SwImageTask : SwTask { auto clipRegion = bbox; + //Convert colorspace if it's not aligned. + if (surface->cs != source->cs) rasterConvertCS(source, surface->cs); + + image.data = source->buffer; + image.w = source->w; + image.h = source->h; + image.stride = source->stride; + //Invisible shape turned to visible by alpha. if ((flags & (RenderUpdateFlag::Image | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) && (opacity > 0)) { imageReset(&image); @@ -709,16 +718,13 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, } -RenderData SwRenderer::prepare(Surface* image, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) +RenderData SwRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) { //prepare task auto task = static_cast(data); if (!task) task = new SwImageTask; if (flags & RenderUpdateFlag::Image) { - task->image.data = image->buffer; - task->image.w = image->w; - task->image.h = image->h; - task->image.stride = image->stride; + task->source = surface; task->mesh = mesh; } return prepareCommon(task, transform, opacity, clips, flags); diff --git a/src/lib/sw_engine/tvgSwRenderer.h b/src/lib/sw_engine/tvgSwRenderer.h index 6ccc7092..56388e36 100644 --- a/src/lib/sw_engine/tvgSwRenderer.h +++ b/src/lib/sw_engine/tvgSwRenderer.h @@ -38,7 +38,7 @@ class SwRenderer : public RenderMethod public: RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags, bool clipper) override; RenderData prepare(const Array& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) override; - RenderData prepare(Surface* image, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) override; + RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) override; bool preRender() override; bool renderShape(RenderData data) override; bool renderImage(RenderData data) override; diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index 17440c1a..67094f7d 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -278,6 +278,11 @@ struct Picture::Impl if (surface) { dup->surface = static_cast(malloc(sizeof(Surface))); *dup->surface = *surface; + //TODO: It needs a better design... + //Backend engines might try to align the colorspace. + //Since it shares the bitmap, duplications should not touch the data. + //Only the owner could manage it. + dup->surface->cs = ColorSpace::Unsupported; } dup->w = w; dup->h = h; diff --git a/src/lib/tvgRender.h b/src/lib/tvgRender.h index 4fafa544..dc4d3969 100644 --- a/src/lib/tvgRender.h +++ b/src/lib/tvgRender.h @@ -210,7 +210,7 @@ public: virtual ~RenderMethod() {} virtual RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags, bool clipper) = 0; virtual RenderData prepare(const Array& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) = 0; - virtual RenderData prepare(Surface* image, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) = 0; + virtual RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array& clips, RenderUpdateFlag flags) = 0; virtual bool preRender() = 0; virtual bool renderShape(RenderData data) = 0; virtual bool renderImage(RenderData data) = 0;