sw_engine: supports the color space conversion.

Currently implements only the necessary functions for converting
between ARGB and ABGR.

Now conversion can be accelerated by the backend engines.
This commit is contained in:
Hermet Park 2023-04-27 14:04:01 +09:00
parent a4b2699f86
commit b733030357
9 changed files with 63 additions and 9 deletions

View file

@ -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<RenderData>& 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<RenderData>& clips, TVG_UNUSED RenderUpdateFlag flags)
{
//TODO:
return nullptr;

View file

@ -32,7 +32,7 @@ public:
RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper) override;
RenderData prepare(const Array<RenderData>& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
RenderData prepare(Surface* image, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
bool preRender() override;
bool renderShape(RenderData data) override;
bool renderImage(RenderData data) override;

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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<RenderData>& clips, RenderUpdateFlag flags)
RenderData SwRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags)
{
//prepare task
auto task = static_cast<SwImageTask*>(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);

View file

@ -38,7 +38,7 @@ class SwRenderer : public RenderMethod
public:
RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper) override;
RenderData prepare(const Array<RenderData>& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
RenderData prepare(Surface* image, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
bool preRender() override;
bool renderShape(RenderData data) override;
bool renderImage(RenderData data) override;

View file

@ -278,6 +278,11 @@ struct Picture::Impl
if (surface) {
dup->surface = static_cast<Surface*>(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;

View file

@ -210,7 +210,7 @@ public:
virtual ~RenderMethod() {}
virtual RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper) = 0;
virtual RenderData prepare(const Array<RenderData>& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
virtual RenderData prepare(Surface* image, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
virtual RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
virtual bool preRender() = 0;
virtual bool renderShape(RenderData data) = 0;
virtual bool renderImage(RenderData data) = 0;