From 38c625d07016f79ed8321701d7fb40f55f5d08c4 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Sat, 30 Dec 2023 15:26:14 +0900 Subject: [PATCH] renderer: enhanced shared surface handling with mutex implementation Introduced a dedicated mutex for each surface instance to ensure safe sharing between the loader, renderer, and engine. This enhancement allows for secure modification and access to bitmap data, addressing potential concurrency issues. Multiple Picture instances can now safely share a single loader instance, optimizing performance. This change builds upon the previous Loader Cache improvements: ff6ea4b6c4564fd6c7c1d8bdde951dc0165e4034 --- src/loaders/external_jpg/tvgJpgLoader.cpp | 35 ++++++------------ src/loaders/external_jpg/tvgJpgLoader.h | 3 -- src/loaders/external_png/tvgPngLoader.cpp | 33 +++++------------ src/loaders/external_png/tvgPngLoader.h | 3 -- src/loaders/external_webp/tvgWebpLoader.cpp | 31 +++++++--------- src/loaders/external_webp/tvgWebpLoader.h | 1 - src/loaders/jpg/tvgJpgLoader.cpp | 32 +++++----------- src/loaders/jpg/tvgJpgLoader.h | 1 - src/loaders/png/tvgPngLoader.cpp | 37 +++++++------------ src/loaders/png/tvgPngLoader.h | 1 - src/loaders/raw/tvgRawLoader.cpp | 41 +++++++-------------- src/loaders/raw/tvgRawLoader.h | 3 -- src/renderer/gl_engine/tvgGlRenderer.h | 2 +- src/renderer/sw_engine/tvgSwCommon.h | 15 +++++++- src/renderer/sw_engine/tvgSwRaster.cpp | 9 +++-- src/renderer/sw_engine/tvgSwRenderer.cpp | 12 ++---- src/renderer/tvgLoadModule.h | 9 ++++- src/renderer/tvgPicture.h | 7 +--- src/renderer/tvgRender.h | 35 +++++++++++++----- src/renderer/wg_engine/tvgWgRenderer.h | 2 +- 20 files changed, 129 insertions(+), 183 deletions(-) diff --git a/src/loaders/external_jpg/tvgJpgLoader.cpp b/src/loaders/external_jpg/tvgJpgLoader.cpp index cb46d5c9..f3838f89 100644 --- a/src/loaders/external_jpg/tvgJpgLoader.cpp +++ b/src/loaders/external_jpg/tvgJpgLoader.cpp @@ -53,7 +53,7 @@ JpgLoader::~JpgLoader() tjDestroy(jpegDecompressor); //This image is shared with raster engine. - tjFree(image); + tjFree(surface.buf8); } @@ -84,7 +84,6 @@ bool JpgLoader::open(const string& path) w = static_cast(width); h = static_cast(height); - cs = ColorSpace::ARGB8888; ret = true; goto finalize; @@ -115,7 +114,6 @@ bool JpgLoader::open(const char* data, uint32_t size, bool copy) w = static_cast(width); h = static_cast(height); - cs = ColorSpace::ARGB8888; this->size = size; return true; @@ -130,8 +128,7 @@ bool JpgLoader::read() /* OPTIMIZE: We assume the desired colorspace is ColorSpace::ARGB How could we notice the renderer colorspace at this time? */ - if (image) tjFree(image); - image = (unsigned char *)tjAlloc(static_cast(w) * static_cast(h) * tjPixelSize[TJPF_BGRX]); + auto image = (unsigned char *)tjAlloc(static_cast(w) * static_cast(h) * tjPixelSize[TJPF_BGRX]); if (!image) return false; //decompress jpg image @@ -142,25 +139,15 @@ bool JpgLoader::read() return false; } + //setup the surface + surface.buf8 = image; + surface.stride = w; + surface.w = w; + surface.h = h; + surface.channelSize = sizeof(uint32_t); + surface.cs = ColorSpace::ARGB8888; + surface.premultiplied = true; + clear(); return true; } - - -Surface* JpgLoader::bitmap() -{ - if (!image) return nullptr; - - //TODO: It's better to keep this surface instance in the loader side - auto surface = new Surface; - surface->buf8 = image; - surface->stride = w; - surface->w = w; - surface->h = h; - surface->cs = cs; - surface->channelSize = sizeof(uint32_t); - surface->premultiplied = true; - surface->owner = true; - - return surface; -} diff --git a/src/loaders/external_jpg/tvgJpgLoader.h b/src/loaders/external_jpg/tvgJpgLoader.h index f9b4c9ea..348dbbf8 100644 --- a/src/loaders/external_jpg/tvgJpgLoader.h +++ b/src/loaders/external_jpg/tvgJpgLoader.h @@ -38,14 +38,11 @@ public: bool open(const char* data, uint32_t size, bool copy) override; bool read() override; - Surface* bitmap() override; - private: void clear(); tjhandle jpegDecompressor; unsigned char* data = nullptr; - unsigned char *image = nullptr; unsigned long size = 0; bool freeData = false; }; diff --git a/src/loaders/external_png/tvgPngLoader.cpp b/src/loaders/external_png/tvgPngLoader.cpp index 4b828c6a..10277f84 100644 --- a/src/loaders/external_png/tvgPngLoader.cpp +++ b/src/loaders/external_png/tvgPngLoader.cpp @@ -48,7 +48,7 @@ PngLoader::PngLoader() : ImageLoader(FileType::Png) PngLoader::~PngLoader() { clear(); - free((void*)content); + free((void*)surface.buf32); } @@ -60,7 +60,6 @@ bool PngLoader::open(const string& path) w = (float)image->width; h = (float)image->height; - cs = ColorSpace::ARGB8888; return true; } @@ -74,7 +73,6 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy) w = (float)image->width; h = (float)image->height; - cs = ColorSpace::ARGB8888; return true; } @@ -98,28 +96,17 @@ bool PngLoader::read() free(buffer); return false; } - content = reinterpret_cast(buffer); + + //setup the surface + surface.buf32 = reinterpret_cast(buffer); + surface.stride = (uint32_t)w; + surface.w = (uint32_t)w; + surface.h = (uint32_t)h; + surface.channelSize = sizeof(uint32_t); + surface.cs = ColorSpace::ARGB8888; + surface.premultiplied = false; clear(); return true; } - - -Surface* PngLoader::bitmap() -{ - if (!content) return nullptr; - - //TODO: It's better to keep this surface instance in the loader side - auto surface = new Surface; - surface->buf32 = content; - surface->stride = (uint32_t)w; - surface->w = (uint32_t)w; - surface->h = (uint32_t)h; - surface->cs = cs; - surface->channelSize = sizeof(uint32_t); - surface->owner = true; - surface->premultiplied = false; - - return surface; -} \ No newline at end of file diff --git a/src/loaders/external_png/tvgPngLoader.h b/src/loaders/external_png/tvgPngLoader.h index c6f04a35..c45544eb 100644 --- a/src/loaders/external_png/tvgPngLoader.h +++ b/src/loaders/external_png/tvgPngLoader.h @@ -36,13 +36,10 @@ public: bool open(const char* data, uint32_t size, bool copy) override; bool read() override; - Surface* bitmap() override; - private: void clear(); png_imagep image = nullptr; - uint32_t* content = nullptr; }; #endif //_TVG_PNG_LOADER_H_ diff --git a/src/loaders/external_webp/tvgWebpLoader.cpp b/src/loaders/external_webp/tvgWebpLoader.cpp index 551a09b6..e7fafdbb 100644 --- a/src/loaders/external_webp/tvgWebpLoader.cpp +++ b/src/loaders/external_webp/tvgWebpLoader.cpp @@ -33,7 +33,16 @@ void WebpLoader::run(unsigned tid) { - image = WebPDecodeBGRA(data, size, nullptr, nullptr); + surface.buf8 = WebPDecodeBGRA(data, size, nullptr, nullptr); + + //setup the surface + surface.stride = (uint32_t)w; + surface.w = (uint32_t)w; + surface.h = (uint32_t)h; + surface.channelSize = sizeof(uint32_t); + surface.cs = ColorSpace::ARGB8888; + surface.premultiplied = false; + } @@ -54,7 +63,7 @@ WebpLoader::~WebpLoader() data = nullptr; size = 0; freeData = false; - WebPFree(image); + WebPFree(surface.buf8); } @@ -82,7 +91,6 @@ bool WebpLoader::open(const string& path) w = static_cast(width); h = static_cast(height); - cs = ColorSpace::ARGB8888; ret = true; @@ -109,7 +117,7 @@ bool WebpLoader::open(const char* data, uint32_t size, bool copy) w = static_cast(width); h = static_cast(height); - cs = ColorSpace::ARGB8888; + surface.cs = ColorSpace::ARGB8888; this->size = size; return true; } @@ -122,6 +130,7 @@ bool WebpLoader::read() if (!data || w == 0 || h == 0) return false; TaskScheduler::request(this); + return true; } @@ -130,17 +139,5 @@ Surface* WebpLoader::bitmap() { this->done(); - if (!image) return nullptr; - - //TODO: It's better to keep this surface instance in the loader side - auto surface = new Surface; - surface->buf8 = image; - surface->stride = static_cast(w); - surface->w = static_cast(w); - surface->h = static_cast(h); - surface->cs = cs; - surface->channelSize = sizeof(uint32_t); - surface->premultiplied = false; - surface->owner = true; - return surface; + return ImageLoader::bitmap(); } \ No newline at end of file diff --git a/src/loaders/external_webp/tvgWebpLoader.h b/src/loaders/external_webp/tvgWebpLoader.h index 4865a588..ad8fb5a6 100644 --- a/src/loaders/external_webp/tvgWebpLoader.h +++ b/src/loaders/external_webp/tvgWebpLoader.h @@ -42,7 +42,6 @@ private: void run(unsigned tid) override; unsigned char* data = nullptr; - unsigned char *image = nullptr; unsigned long size = 0; bool freeData = false; }; diff --git a/src/loaders/jpg/tvgJpgLoader.cpp b/src/loaders/jpg/tvgJpgLoader.cpp index 7c3bf514..611d3474 100644 --- a/src/loaders/jpg/tvgJpgLoader.cpp +++ b/src/loaders/jpg/tvgJpgLoader.cpp @@ -39,11 +39,13 @@ void JpgLoader::clear() void JpgLoader::run(unsigned tid) { - if (image) { - free(image); - image = nullptr; - } - image = jpgdDecompress(decoder); + surface.buf8 = jpgdDecompress(decoder); + surface.stride = static_cast(w); + surface.w = static_cast(w); + surface.h = static_cast(h); + surface.cs = ColorSpace::ARGB8888; + surface.channelSize = sizeof(uint32_t); + surface.premultiplied = true; clear(); } @@ -62,7 +64,7 @@ JpgLoader::JpgLoader() : ImageLoader(FileType::Jpg) JpgLoader::~JpgLoader() { clear(); - free(image); + free(surface.buf8); } @@ -74,7 +76,6 @@ bool JpgLoader::open(const string& path) w = static_cast(width); h = static_cast(height); - cs = ColorSpace::ARGB8888; return true; } @@ -98,7 +99,6 @@ bool JpgLoader::open(const char* data, uint32_t size, bool copy) w = static_cast(width); h = static_cast(height); - cs = ColorSpace::ARGB8888; return true; } @@ -128,19 +128,5 @@ bool JpgLoader::close() Surface* JpgLoader::bitmap() { this->done(); - - if (!image) return nullptr; - - //TODO: It's better to keep this surface instance in the loader side - auto surface = new Surface; - surface->buf8 = image; - surface->stride = static_cast(w); - surface->w = static_cast(w); - surface->h = static_cast(h); - surface->cs = cs; - surface->channelSize = sizeof(uint32_t); - surface->premultiplied = true; - surface->owner = true; - - return surface; + return ImageLoader::bitmap(); } \ No newline at end of file diff --git a/src/loaders/jpg/tvgJpgLoader.h b/src/loaders/jpg/tvgJpgLoader.h index 9e78282c..05cbb54c 100644 --- a/src/loaders/jpg/tvgJpgLoader.h +++ b/src/loaders/jpg/tvgJpgLoader.h @@ -32,7 +32,6 @@ class JpgLoader : public ImageLoader, public Task private: jpeg_decoder* decoder = nullptr; char* data = nullptr; - unsigned char *image = nullptr; bool freeData = false; void clear(); diff --git a/src/loaders/png/tvgPngLoader.cpp b/src/loaders/png/tvgPngLoader.cpp index 7e84839c..c8920dce 100644 --- a/src/loaders/png/tvgPngLoader.cpp +++ b/src/loaders/png/tvgPngLoader.cpp @@ -32,16 +32,19 @@ void PngLoader::run(unsigned tid) { - if (image) { - free(image); - image = nullptr; - } auto width = static_cast(w); auto height = static_cast(h); - if (lodepng_decode(&image, &width, &height, &state, data, size)) { + if (lodepng_decode(&surface.buf8, &width, &height, &state, data, size)) { TVGERR("PNG", "Failed to decode image"); } + + //setup the surface + surface.stride = width; + surface.w = width; + surface.h = height; + surface.channelSize = sizeof(uint32_t); + surface.premultiplied = false; } @@ -58,7 +61,7 @@ PngLoader::PngLoader() : ImageLoader(FileType::Png) PngLoader::~PngLoader() { if (freeData) free(data); - free(image); + free(surface.buf8); lodepng_state_cleanup(&state); } @@ -90,8 +93,8 @@ bool PngLoader::open(const string& path) w = static_cast(width); h = static_cast(height); - if (state.info_png.color.colortype == LCT_RGBA) cs = ColorSpace::ABGR8888; - else cs = ColorSpace::ARGB8888; + if (state.info_png.color.colortype == LCT_RGBA) surface.cs = ColorSpace::ABGR8888; + else surface.cs = ColorSpace::ARGB8888; ret = true; @@ -122,7 +125,7 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy) h = static_cast(height); this->size = size; - cs = ColorSpace::ABGR8888; + surface.cs = ColorSpace::ABGR8888; return true; } @@ -143,19 +146,5 @@ bool PngLoader::read() Surface* PngLoader::bitmap() { this->done(); - - if (!image) return nullptr; - - //TODO: It's better to keep this surface instance in the loader side - auto surface = new Surface; - surface->buf8 = image; - surface->stride = static_cast(w); - surface->w = static_cast(w); - surface->h = static_cast(h); - surface->cs = cs; - surface->channelSize = sizeof(uint32_t); - surface->premultiplied = false; - surface->owner = true; - - return surface; + return ImageLoader::bitmap(); } \ No newline at end of file diff --git a/src/loaders/png/tvgPngLoader.h b/src/loaders/png/tvgPngLoader.h index 2de33f5a..06fbbf73 100644 --- a/src/loaders/png/tvgPngLoader.h +++ b/src/loaders/png/tvgPngLoader.h @@ -32,7 +32,6 @@ class PngLoader : public ImageLoader, public Task private: LodePNGState state; unsigned char* data = nullptr; - unsigned char *image = nullptr; unsigned long size = 0; bool freeData = false; diff --git a/src/loaders/raw/tvgRawLoader.cpp b/src/loaders/raw/tvgRawLoader.cpp index 84c9e50d..b797f982 100644 --- a/src/loaders/raw/tvgRawLoader.cpp +++ b/src/loaders/raw/tvgRawLoader.cpp @@ -41,10 +41,7 @@ RawLoader::RawLoader() : ImageLoader(FileType::Raw) RawLoader::~RawLoader() { - if (copy && content) { - free((void*)content); - content = nullptr; - } + if (copy) free(surface.buf32); } @@ -59,13 +56,19 @@ bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) this->copy = copy; if (copy) { - content = (uint32_t*)malloc(sizeof(uint32_t) * w * h); - if (!content) return false; - memcpy((void*)content, data, sizeof(uint32_t) * w * h); + surface.buf32 = (uint32_t*)malloc(sizeof(uint32_t) * w * h); + if (!surface.buf32) return false; + memcpy((void*)surface.buf32, data, sizeof(uint32_t) * w * h); } - else content = const_cast(data); + else surface.buf32 = const_cast(data); - cs = ColorSpace::ARGB8888; + //setup the surface + surface.stride = w; + surface.w = w; + surface.h = h; + surface.cs = ColorSpace::ARGB8888; + surface.channelSize = sizeof(uint32_t); + surface.premultiplied = true; return true; } @@ -74,24 +77,6 @@ bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) bool RawLoader::read() { LoadModule::read(); + return true; } - - -Surface* RawLoader::bitmap() -{ - if (!content) return nullptr; - - //TODO: It's better to keep this surface instance in the loader side - auto surface = new Surface; - surface->buf32 = content; - surface->stride = static_cast(w); - surface->w = static_cast(w); - surface->h = static_cast(h); - surface->cs = cs; - surface->channelSize = sizeof(uint32_t); - surface->premultiplied = true; - surface->owner = true; - - return surface; -} diff --git a/src/loaders/raw/tvgRawLoader.h b/src/loaders/raw/tvgRawLoader.h index eb01c6f2..970cdd9c 100644 --- a/src/loaders/raw/tvgRawLoader.h +++ b/src/loaders/raw/tvgRawLoader.h @@ -26,7 +26,6 @@ class RawLoader : public ImageLoader { public: - uint32_t* content = nullptr; bool copy = false; RawLoader(); @@ -35,8 +34,6 @@ public: using LoadModule::open; bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy); bool read() override; - - Surface* bitmap() override; }; diff --git a/src/renderer/gl_engine/tvgGlRenderer.h b/src/renderer/gl_engine/tvgGlRenderer.h index 219a43b6..035582ba 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.h +++ b/src/renderer/gl_engine/tvgGlRenderer.h @@ -50,7 +50,7 @@ public: RT_None, }; - Surface surface = {nullptr, 0, 0, 0, ColorSpace::Unsupported, true}; + Surface surface; RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) override; RenderData prepare(const Array& scene, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags) override; diff --git a/src/renderer/sw_engine/tvgSwCommon.h b/src/renderer/sw_engine/tvgSwCommon.h index f0f57506..3d73075a 100644 --- a/src/renderer/sw_engine/tvgSwCommon.h +++ b/src/renderer/sw_engine/tvgSwCommon.h @@ -261,13 +261,26 @@ struct SwSurface : Surface SwAlpha alphas[4]; //Alpha:2, InvAlpha:3, Luma:4, InvLuma:5 SwBlender blender = nullptr; //blender (optional) SwCompositor* compositor = nullptr; //compositor (optional) - BlendMethod blendMethod; //blending method (uint8_t) + BlendMethod blendMethod; //blending method (uint8_t) SwAlpha alpha(CompositeMethod method) { auto idx = (int)(method) - 2; //0: None, 1: ClipPath return alphas[idx > 3 ? 0 : idx]; //CompositeMethod has only four Matting methods. } + + SwSurface() + { + } + + SwSurface(const SwSurface* rhs) : Surface(rhs) + { + join = rhs->join; + memcpy(alphas, rhs->alphas, sizeof(alphas)); + blender = rhs->blender; + compositor = rhs->compositor; + blendMethod = rhs->blendMethod; + } }; struct SwCompositor : Compositor diff --git a/src/renderer/sw_engine/tvgSwRaster.cpp b/src/renderer/sw_engine/tvgSwRaster.cpp index 4e9fd894..9a6dc459 100644 --- a/src/renderer/sw_engine/tvgSwRaster.cpp +++ b/src/renderer/sw_engine/tvgSwRaster.cpp @@ -1855,7 +1855,9 @@ void rasterUnpremultiply(Surface* surface) void rasterPremultiply(Surface* surface) { - if (surface->channelSize != sizeof(uint32_t)) return; + unique_lock lock{surface->mtx}; + if (surface->premultiplied || (surface->channelSize != sizeof(uint32_t))) return; + surface->premultiplied = true; TVGLOG("SW_ENGINE", "Premultiply [Size: %d x %d]", surface->w, surface->h); @@ -1869,7 +1871,6 @@ void rasterPremultiply(Surface* surface) *dst = (c & 0xff000000) + ((((c >> 8) & 0xff) * a) & 0xff00) + ((((c & 0x00ff00ff) * a) >> 8) & 0x00ff00ff); } } - surface->premultiplied = true; } @@ -1935,6 +1936,9 @@ bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, con bool rasterConvertCS(Surface* surface, ColorSpace to) { + unique_lock lock{surface->mtx}; + if (surface->cs == to) return true; + //TOOD: Support SIMD accelerations auto from = surface->cs; @@ -1946,6 +1950,5 @@ bool rasterConvertCS(Surface* surface, ColorSpace to) surface->cs = to; return cRasterARGBtoABGR(surface); } - return false; } diff --git a/src/renderer/sw_engine/tvgSwRenderer.cpp b/src/renderer/sw_engine/tvgSwRenderer.cpp index b1ca5525..c9c543fb 100644 --- a/src/renderer/sw_engine/tvgSwRenderer.cpp +++ b/src/renderer/sw_engine/tvgSwRenderer.cpp @@ -281,10 +281,8 @@ struct SwImageTask : SwTask auto clipRegion = bbox; //Convert colorspace if it's not aligned. - if (source->owner) { - if (source->cs != surface->cs) rasterConvertCS(source, surface->cs); - if (!source->premultiplied) rasterPremultiply(source); - } + rasterConvertCS(source, surface->cs); + rasterPremultiply(source); image.data = source->data; image.w = source->w; @@ -436,7 +434,6 @@ bool SwRenderer::target(pixel_t* data, uint32_t stride, uint32_t w, uint32_t h, surface->cs = cs; surface->channelSize = CHANNEL_SIZE(cs); surface->premultiplied = true; - surface->owner = true; vport.x = vport.y = 0; vport.w = surface->w; @@ -638,11 +635,8 @@ Compositor* SwRenderer::target(const RenderRegion& region, ColorSpace cs) //New Composition if (!cmp) { - cmp = new SwSurface; - //Inherits attributes from main surface - *cmp = *surface; - + cmp = new SwSurface(surface); cmp->compositor = new SwCompositor; //TODO: We can optimize compositor surface size from (surface->stride x surface->h) to Parameter(w x h) diff --git a/src/renderer/tvgLoadModule.h b/src/renderer/tvgLoadModule.h index dbc4a252..0ea76639 100644 --- a/src/renderer/tvgLoadModule.h +++ b/src/renderer/tvgLoadModule.h @@ -69,13 +69,18 @@ struct LoadModule struct ImageLoader : LoadModule { float w = 0, h = 0; //default image size - ColorSpace cs = ColorSpace::Unsupported; //must be clarified at open() + Surface surface; ImageLoader(FileType type) : LoadModule(type) {} virtual bool animatable() { return false; } //true if this loader supports animation. - virtual Surface* bitmap() { return nullptr; } virtual Paint* paint() { return nullptr; } + + virtual Surface* bitmap() + { + if (surface.data) return &surface; + return nullptr; + } }; diff --git a/src/renderer/tvgPicture.h b/src/renderer/tvgPicture.h index 5658894d..26a171ba 100644 --- a/src/renderer/tvgPicture.h +++ b/src/renderer/tvgPicture.h @@ -83,7 +83,6 @@ struct Picture::Impl { LoaderMgr::retrieve(loader); delete(paint); - delete(surface); } bool dispose(RenderMethod& renderer) @@ -206,11 +205,7 @@ struct Picture::Impl ++dup->loader->sharing; } - if (surface) { - dup->surface = new Surface; - *dup->surface = *surface; - dup->surface->owner = false; - } + dup->surface = surface; dup->w = w; dup->h = h; dup->resizing = resizing; diff --git a/src/renderer/tvgRender.h b/src/renderer/tvgRender.h index 43d6e526..1e70b534 100644 --- a/src/renderer/tvgRender.h +++ b/src/renderer/tvgRender.h @@ -23,6 +23,7 @@ #ifndef _TVG_RENDER_H_ #define _TVG_RENDER_H_ +#include #include "tvgCommon.h" #include "tvgArray.h" @@ -49,17 +50,33 @@ enum ColorSpace struct Surface { union { - pixel_t* data; //system based data pointer - uint32_t* buf32; //for explicit 32bits channels - uint8_t* buf8; //for explicit 8bits grayscale + pixel_t* data = nullptr; //system based data pointer + uint32_t* buf32; //for explicit 32bits channels + uint8_t* buf8; //for explicit 8bits grayscale }; - uint32_t stride; - uint32_t w, h; - ColorSpace cs; - uint8_t channelSize; + mutex mtx; //used for thread safety + uint32_t stride = 0; + uint32_t w = 0, h = 0; + ColorSpace cs = ColorSpace::Unsupported; + uint8_t channelSize = 0; + bool premultiplied = 0; //Alpha-premultiplied + + Surface() + { + } + + Surface(const Surface* rhs) + { + data = rhs->data; + stride = rhs->stride; + w = rhs->w; + h = rhs->h; + cs = rhs->cs; + channelSize = rhs->channelSize; + premultiplied = rhs->premultiplied; + } + - bool premultiplied; //Alpha-premultiplied - bool owner; //Only owner could modify the buffer }; struct Compositor diff --git a/src/renderer/wg_engine/tvgWgRenderer.h b/src/renderer/wg_engine/tvgWgRenderer.h index 0236247a..19058bc2 100644 --- a/src/renderer/wg_engine/tvgWgRenderer.h +++ b/src/renderer/wg_engine/tvgWgRenderer.h @@ -67,7 +67,7 @@ private: WgRenderTarget mRenderTarget; WGPUSurface mSurface{}; WGPUSwapChain mSwapChain{}; - Surface mTargetSurface = { nullptr, 0, 0, 0, ColorSpace::Unsupported, true }; + Surface mTargetSurface; }; #endif /* _TVG_WG_RENDERER_H_ */