engine/loaders: develop the ColorSpace feature infrastructure

Replace the existing fragile usage of the colorspace data type
with a new and robust concrete ColorSpace type.
This commit is contained in:
Hermet Park 2023-04-27 11:34:39 +09:00
parent bce5aef068
commit cf4484c1ad
19 changed files with 79 additions and 66 deletions

View file

@ -123,10 +123,10 @@ bool GlRenderer::endComposite(TVG_UNUSED Compositor* cmp)
} }
int32_t GlRenderer::colorSpace() ColorSpace GlRenderer::colorSpace()
{ {
//TODO: return a proper color space value. //TODO: return a proper color space value.
return -1; return ColorSpace::Unsupported;
} }

View file

@ -50,7 +50,7 @@ public:
bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) override; bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) override;
bool endComposite(Compositor* cmp) override; bool endComposite(Compositor* cmp) override;
uint32_t colorSpace() override; ColorSpace colorSpace() override;
static GlRenderer* gen(); static GlRenderer* gen();
static int init(TVG_UNUSED uint32_t threads); static int init(TVG_UNUSED uint32_t threads);

View file

@ -1452,10 +1452,10 @@ void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len)
bool rasterCompositor(SwSurface* surface) bool rasterCompositor(SwSurface* surface)
{ {
if (surface->cs == SwCanvas::ABGR8888 || surface->cs == SwCanvas::ABGR8888_STRAIGHT) { if (surface->cs == ColorSpace::ABGR8888 || surface->cs == ColorSpace::ABGR8888S) {
surface->blender.join = _abgrJoin; surface->blender.join = _abgrJoin;
surface->blender.lumaValue = _abgrLumaValue; surface->blender.lumaValue = _abgrLumaValue;
} else if (surface->cs == SwCanvas::ARGB8888 || surface->cs == SwCanvas::ARGB8888_STRAIGHT) { } else if (surface->cs == ColorSpace::ARGB8888 || surface->cs == ColorSpace::ARGB8888S) {
surface->blender.join = _argbJoin; surface->blender.join = _argbJoin;
surface->blender.lumaValue = _argbLumaValue; surface->blender.lumaValue = _argbLumaValue;
} else { } else {

View file

@ -407,7 +407,7 @@ bool SwRenderer::viewport(const RenderRegion& vp)
} }
bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t colorSpace) bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, ColorSpace cs)
{ {
if (!buffer || stride == 0 || w == 0 || h == 0 || w > stride) return false; if (!buffer || stride == 0 || w == 0 || h == 0 || w > stride) return false;
@ -417,7 +417,7 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
surface->stride = stride; surface->stride = stride;
surface->w = w; surface->w = w;
surface->h = h; surface->h = h;
surface->cs = colorSpace; surface->cs = cs;
vport.x = vport.y = 0; vport.x = vport.y = 0;
vport.w = surface->w; vport.w = surface->w;
@ -447,7 +447,7 @@ void SwRenderer::clearCompositors()
bool SwRenderer::postRender() bool SwRenderer::postRender()
{ {
//Unmultiply alpha if needed //Unmultiply alpha if needed
if (surface->cs == SwCanvas::ABGR8888_STRAIGHT || surface->cs == SwCanvas::ARGB8888_STRAIGHT) { if (surface->cs == ColorSpace::ABGR8888S || surface->cs == ColorSpace::ARGB8888S) {
rasterUnpremultiply(surface); rasterUnpremultiply(surface);
} }
@ -755,10 +755,10 @@ SwRenderer::SwRenderer():mpool(globalMpool)
} }
uint32_t SwRenderer::colorSpace() ColorSpace SwRenderer::colorSpace()
{ {
if (surface) return surface->cs; if (surface) return surface->cs;
return tvg::SwCanvas::ARGB8888; return ColorSpace::Unsupported;
} }

View file

@ -50,7 +50,7 @@ public:
bool clear() override; bool clear() override;
bool sync() override; bool sync() override;
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t colorSpace); bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, ColorSpace cs);
bool mempool(bool shared); bool mempool(bool shared);
Compositor* target(const RenderRegion& region) override; Compositor* target(const RenderRegion& region) override;
@ -58,7 +58,7 @@ public:
bool endComposite(Compositor* cmp) override; bool endComposite(Compositor* cmp) override;
void clearCompositors(); void clearCompositors();
uint32_t colorSpace() override; ColorSpace colorSpace() override;
static SwRenderer* gen(); static SwRenderer* gen();
static bool init(uint32_t threads); static bool init(uint32_t threads);

View file

@ -37,7 +37,7 @@ public:
float vw = 0; float vw = 0;
float vh = 0; float vh = 0;
float w = 0, h = 0; //default image size float w = 0, h = 0; //default image size
uint32_t colorSpace = SwCanvas::ARGB8888; ColorSpace cs = ColorSpace::ARGB8888;
virtual ~LoadModule() {} virtual ~LoadModule() {}
@ -50,7 +50,7 @@ public:
virtual bool read() = 0; virtual bool read() = 0;
virtual bool close() = 0; virtual bool close() = 0;
virtual unique_ptr<Surface> bitmap(uint32_t colorSpace) { return nullptr; } virtual unique_ptr<Surface> bitmap(ColorSpace cs) { return nullptr; }
virtual unique_ptr<Paint> paint() { return nullptr; } virtual unique_ptr<Paint> paint() { return nullptr; }
}; };

View file

@ -66,7 +66,7 @@ struct Picture::Impl
Surface* surface = nullptr; //bitmap picture uses Surface* surface = nullptr; //bitmap picture uses
RenderData rd = nullptr; //engine data RenderData rd = nullptr; //engine data
float w = 0, h = 0; float w = 0, h = 0;
uint32_t rendererColorSpace = 0; ColorSpace rendererColorSpace = ColorSpace::Unsupported;
RenderMesh rm; //mesh data RenderMesh rm; //mesh data
bool resizing = false; bool resizing = false;

View file

@ -29,19 +29,30 @@
namespace tvg namespace tvg
{ {
using RenderData = void*;
enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, All = 255}; enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, All = 255};
struct Surface;
enum ColorSpace
{
ABGR8888 = 0, //The channels are joined in the order: alpha, blue, green, red. Colors are alpha-premultiplied.
ARGB8888, //The channels are joined in the order: alpha, red, green, blue. Colors are alpha-premultiplied.
ABGR8888S, //The channels are joined in the order: alpha, blue, green, red. Colors are un-alpha-premultiplied.
ARGB8888S, //The channels are joined in the order: alpha, red, green, blue. Colors are un-alpha-premultiplied.
Unsupported //TODO: Change to the default, At the moment, we put it in the last to align with SwCanvas::Colorspace.
};
struct Surface struct Surface
{ {
//TODO: Union for multiple types //TODO: Union for multiple types
uint32_t* buffer; uint32_t* buffer;
uint32_t stride; uint32_t stride;
uint32_t w, h; uint32_t w, h;
uint32_t cs; ColorSpace cs;
}; };
using RenderData = void*;
struct Compositor struct Compositor
{ {
CompositeMethod method; CompositeMethod method;
@ -216,7 +227,7 @@ public:
virtual bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) = 0; virtual bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) = 0;
virtual bool endComposite(Compositor* cmp) = 0; virtual bool endComposite(Compositor* cmp) = 0;
virtual uint32_t colorSpace() = 0; virtual ColorSpace colorSpace() = 0;
}; };
} }

View file

@ -85,7 +85,7 @@ Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
auto renderer = static_cast<SwRenderer*>(Canvas::pImpl->renderer); auto renderer = static_cast<SwRenderer*>(Canvas::pImpl->renderer);
if (!renderer) return Result::MemoryCorruption; if (!renderer) return Result::MemoryCorruption;
if (!renderer->target(buffer, stride, w, h, cs)) return Result::InvalidArguments; if (!renderer->target(buffer, stride, w, h, static_cast<ColorSpace>(cs))) return Result::InvalidArguments;
//Paints must be updated again with this new target. //Paints must be updated again with this new target.
Canvas::pImpl->needRefresh(); Canvas::pImpl->needRefresh();

View file

@ -29,29 +29,22 @@
/* Internal Class Implementation */ /* Internal Class Implementation */
/************************************************************************/ /************************************************************************/
void JpgLoader::clear() static uint32_t convertColorSpaceType(ColorSpace cs)
{
if (freeData) free(data);
data = nullptr;
size = 0;
freeData = false;
}
uint32_t convertColorSpaceType(uint32_t colorSpace)
{ {
uint32_t tjpfColorSpace = TJPF_RGBX; uint32_t tjpfColorSpace = TJPF_RGBX;
switch (colorSpace)
{ switch (cs) {
case SwCanvas::ARGB8888: case ColorSpace::ARGB8888:
case SwCanvas::ARGB8888_STRAIGHT: case ColorSpace::ARGB8888S:
default: default:
tjpfColorSpace = TJPF_BGRX; tjpfColorSpace = TJPF_BGRX;
break; break;
case SwCanvas::ABGR8888: case ColorSpace::ABGR8888:
case SwCanvas::ABGR8888_STRAIGHT: case ColorSpace::ABGR8888S:
tjpfColorSpace = TJPF_RGBX; tjpfColorSpace = TJPF_RGBX;
break; break;
} }
return tjpfColorSpace; return tjpfColorSpace;
} }
@ -73,6 +66,15 @@ static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
} }
} }
void JpgLoader::clear()
{
if (freeData) free(data);
data = nullptr;
size = 0;
freeData = false;
}
/************************************************************************/ /************************************************************************/
/* External Class Implementation */ /* External Class Implementation */
/************************************************************************/ /************************************************************************/
@ -163,11 +165,11 @@ bool JpgLoader::open(const char* data, uint32_t size, bool copy)
bool JpgLoader::read() bool JpgLoader::read()
{ {
if (image) tjFree(image); if (image) tjFree(image);
image = (unsigned char *)tjAlloc(static_cast<int>(w) * static_cast<int>(h) * tjPixelSize[convertColorSpaceType(colorSpace)]); image = (unsigned char *)tjAlloc(static_cast<int>(w) * static_cast<int>(h) * tjPixelSize[convertColorSpaceType(cs)]);
if (!image) return false; if (!image) return false;
//decompress jpg image //decompress jpg image
if (tjDecompress2(jpegDecompressor, data, size, image, static_cast<int>(w), 0, static_cast<int>(h), convertColorSpaceType(colorSpace), 0) < 0) { if (tjDecompress2(jpegDecompressor, data, size, image, static_cast<int>(w), 0, static_cast<int>(h), convertColorSpaceType(cs), 0) < 0) {
TVGERR("JPG LOADER", "%s", tjGetErrorStr()); TVGERR("JPG LOADER", "%s", tjGetErrorStr());
tjFree(image); tjFree(image);
image = nullptr; image = nullptr;
@ -185,11 +187,11 @@ bool JpgLoader::close()
} }
unique_ptr<Surface> JpgLoader::bitmap(uint32_t colorSpace) unique_ptr<Surface> JpgLoader::bitmap(ColorSpace cs)
{ {
if (!image) return nullptr; if (!image) return nullptr;
if (this->colorSpace != colorSpace) { if (this->cs != cs) {
this->colorSpace = colorSpace; this->cs = cs;
_changeColorSpace(reinterpret_cast<uint32_t*>(image), w, h); _changeColorSpace(reinterpret_cast<uint32_t*>(image), w, h);
} }
@ -198,7 +200,7 @@ unique_ptr<Surface> JpgLoader::bitmap(uint32_t colorSpace)
surface->stride = w; surface->stride = w;
surface->w = w; surface->w = w;
surface->h = h; surface->h = h;
surface->cs = colorSpace; surface->cs = cs;
return unique_ptr<Surface>(surface); return unique_ptr<Surface>(surface);
} }

View file

@ -38,7 +38,7 @@ public:
bool read() override; bool read() override;
bool close() override; bool close() override;
unique_ptr<Surface> bitmap(uint32_t colorSpace) override; unique_ptr<Surface> bitmap(ColorSpace cs) override;
private: private:
void clear(); void clear();

View file

@ -128,11 +128,11 @@ bool PngLoader::close()
return true; return true;
} }
unique_ptr<Surface> PngLoader::bitmap(uint32_t colorSpace) unique_ptr<Surface> PngLoader::bitmap(ColorSpace cs)
{ {
if (!content) return nullptr; if (!content) return nullptr;
if (this->colorSpace != colorSpace) { if (this->cs != cs) {
this->colorSpace = colorSpace; this->cs = cs;
_changeColorSpace(content, w, h); _changeColorSpace(content, w, h);
} }
@ -141,7 +141,7 @@ unique_ptr<Surface> PngLoader::bitmap(uint32_t colorSpace)
surface->stride = w; surface->stride = w;
surface->w = w; surface->w = w;
surface->h = h; surface->h = h;
surface->cs = colorSpace; surface->cs = cs;
return unique_ptr<Surface>(surface); return unique_ptr<Surface>(surface);
} }

View file

@ -37,7 +37,7 @@ public:
bool read() override; bool read() override;
bool close() override; bool close() override;
unique_ptr<Surface> bitmap(uint32_t colorSpace) override; unique_ptr<Surface> bitmap(ColorSpace cs) override;
private: private:
png_imagep image = nullptr; png_imagep image = nullptr;

View file

@ -128,13 +128,13 @@ bool JpgLoader::close()
} }
unique_ptr<Surface> JpgLoader::bitmap(uint32_t colorSpace) unique_ptr<Surface> JpgLoader::bitmap(ColorSpace cs)
{ {
this->done(); this->done();
if (!image) return nullptr; if (!image) return nullptr;
if (this->colorSpace != colorSpace) { if (this->cs != cs) {
this->colorSpace = colorSpace; this->cs = cs;
_changeColorSpace(reinterpret_cast<uint32_t*>(image), static_cast<uint32_t>(w), static_cast<uint32_t>(h)); _changeColorSpace(reinterpret_cast<uint32_t*>(image), static_cast<uint32_t>(w), static_cast<uint32_t>(h));
} }
@ -143,7 +143,7 @@ unique_ptr<Surface> JpgLoader::bitmap(uint32_t colorSpace)
surface->stride = static_cast<uint32_t>(w); surface->stride = static_cast<uint32_t>(w);
surface->w = static_cast<uint32_t>(w); surface->w = static_cast<uint32_t>(w);
surface->h = static_cast<uint32_t>(h); surface->h = static_cast<uint32_t>(h);
surface->cs = colorSpace; surface->cs = cs;
return unique_ptr<Surface>(surface); return unique_ptr<Surface>(surface);
} }

View file

@ -45,7 +45,7 @@ public:
bool read() override; bool read() override;
bool close() override; bool close() override;
unique_ptr<Surface> bitmap(uint32_t colorSpace) override; unique_ptr<Surface> bitmap(ColorSpace cs) override;
void run(unsigned tid) override; void run(unsigned tid) override;
}; };

View file

@ -125,7 +125,7 @@ bool PngLoader::open(const string& path)
h = static_cast<float>(height); h = static_cast<float>(height);
ret = true; ret = true;
if (state.info_png.color.colortype == LCT_RGBA) colorSpace = SwCanvas::ABGR8888; if (state.info_png.color.colortype == LCT_RGBA) cs = ColorSpace::ABGR8888;
goto finalize; goto finalize;
@ -161,7 +161,7 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy)
h = static_cast<float>(height); h = static_cast<float>(height);
this->size = size; this->size = size;
if (state.info_png.color.colortype == LCT_RGBA) colorSpace = SwCanvas::ABGR8888; if (state.info_png.color.colortype == LCT_RGBA) cs = ColorSpace::ABGR8888;
return true; return true;
} }
@ -185,13 +185,13 @@ bool PngLoader::close()
} }
unique_ptr<Surface> PngLoader::bitmap(uint32_t colorSpace) unique_ptr<Surface> PngLoader::bitmap(ColorSpace cs)
{ {
this->done(); this->done();
if (!image) return nullptr; if (!image) return nullptr;
if (this->colorSpace != colorSpace) { if (this->cs != cs) {
this->colorSpace = colorSpace; this->cs = cs;
_changeColorSpace(reinterpret_cast<uint32_t*>(image), static_cast<uint32_t>(w), static_cast<uint32_t>(h)); _changeColorSpace(reinterpret_cast<uint32_t*>(image), static_cast<uint32_t>(w), static_cast<uint32_t>(h));
} }
@ -200,7 +200,7 @@ unique_ptr<Surface> PngLoader::bitmap(uint32_t colorSpace)
surface->stride = static_cast<uint32_t>(w); surface->stride = static_cast<uint32_t>(w);
surface->w = static_cast<uint32_t>(w); surface->w = static_cast<uint32_t>(w);
surface->h = static_cast<uint32_t>(h); surface->h = static_cast<uint32_t>(h);
surface->cs = colorSpace; surface->cs = cs;
return unique_ptr<Surface>(surface); return unique_ptr<Surface>(surface);
} }

View file

@ -48,7 +48,7 @@ public:
bool read() override; bool read() override;
bool close() override; bool close() override;
unique_ptr<Surface> bitmap(uint32_t colorSpace) override; unique_ptr<Surface> bitmap(ColorSpace cs) override;
void run(unsigned tid) override; void run(unsigned tid) override;
}; };

View file

@ -90,11 +90,11 @@ bool RawLoader::close()
} }
unique_ptr<Surface> RawLoader::bitmap(uint32_t colorSpace) unique_ptr<Surface> RawLoader::bitmap(ColorSpace cs)
{ {
if (!content) return nullptr; if (!content) return nullptr;
if (this->colorSpace != colorSpace) { if (this->cs != cs) {
this->colorSpace = colorSpace; this->cs = cs;
_changeColorSpace(content, static_cast<uint32_t>(w), static_cast<uint32_t>(h)); _changeColorSpace(content, static_cast<uint32_t>(w), static_cast<uint32_t>(h));
} }
@ -103,7 +103,7 @@ unique_ptr<Surface> RawLoader::bitmap(uint32_t colorSpace)
surface->stride = static_cast<uint32_t>(w); surface->stride = static_cast<uint32_t>(w);
surface->w = static_cast<uint32_t>(w); surface->w = static_cast<uint32_t>(w);
surface->h = static_cast<uint32_t>(h); surface->h = static_cast<uint32_t>(h);
surface->cs = colorSpace; surface->cs = cs;
return unique_ptr<Surface>(surface); return unique_ptr<Surface>(surface);
} }

View file

@ -36,7 +36,7 @@ public:
bool read() override; bool read() override;
bool close() override; bool close() override;
unique_ptr<Surface> bitmap(uint32_t colorSpace) override; unique_ptr<Surface> bitmap(ColorSpace cs) override;
}; };