From 8f4e66d1a21fdccbbfdf639df09248397499b56e Mon Sep 17 00:00:00 2001 From: Martin Capitanio Date: Fri, 26 Jan 2024 10:04:27 +0100 Subject: [PATCH] ThorVG: update from v0.12.1 to v0.12.3 https://github.com/thorvg/thorvg/releases/tag/v0.12.3 + Full Changelog: https://github.com/thorvg/thorvg/compare/v0.12.1...v0.12.3 Godot-related SVG bug fixes: + svg_loader: Add missing transform functions skewX and skewY. thorvg/thorvg#1928 + sw_engine: Rectified dash line drawing issue. thorvg/thorvg#1932 (cherry picked from commit 73589f6db604c9c93d3c5ab4cc2cd51f9628256f) --- thirdparty/README.md | 2 +- thirdparty/thorvg/inc/config.h | 2 +- thirdparty/thorvg/src/common/tvgLock.h | 70 +++++++++++++++++++ .../thorvg/src/loaders/svg/tvgSvgLoader.cpp | 52 +++++--------- .../src/renderer/sw_engine/tvgSwRaster.cpp | 28 ++++---- .../renderer/sw_engine/tvgSwRasterTexmap.h | 8 +-- .../src/renderer/sw_engine/tvgSwRenderer.cpp | 3 +- .../src/renderer/sw_engine/tvgSwShape.cpp | 45 ++---------- thirdparty/thorvg/src/renderer/tvgLoader.cpp | 17 ++--- thirdparty/thorvg/src/renderer/tvgRender.h | 4 +- thirdparty/thorvg/src/renderer/tvgShape.cpp | 12 ++-- .../thorvg/src/renderer/tvgTaskScheduler.cpp | 60 +++++++++++----- .../thorvg/src/renderer/tvgTaskScheduler.h | 46 ++++++++---- thirdparty/thorvg/update-thorvg.sh | 2 +- 14 files changed, 209 insertions(+), 142 deletions(-) create mode 100644 thirdparty/thorvg/src/common/tvgLock.h diff --git a/thirdparty/README.md b/thirdparty/README.md index a578b8f194e6..d38041402a31 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -825,7 +825,7 @@ instead of `miniz.h` as an external dependency. ## thorvg - Upstream: https://github.com/thorvg/thorvg -- Version: 0.12.1 (d761e3c5622c0ffba2e5bb40da05751e2451e495, 2024) +- Version: 0.12.3 (9d79f0ccef632fd3b43b8ea02def529b6a8d2288, 2024) - License: MIT Files extracted from upstream source: diff --git a/thirdparty/thorvg/inc/config.h b/thirdparty/thorvg/inc/config.h index 73e72c74a79b..ef65b1500d89 100644 --- a/thirdparty/thorvg/inc/config.h +++ b/thirdparty/thorvg/inc/config.h @@ -9,5 +9,5 @@ // For internal debugging: //#define THORVG_LOG_ENABLED -#define THORVG_VERSION_STRING "0.12.1" +#define THORVG_VERSION_STRING "0.12.3" #endif diff --git a/thirdparty/thorvg/src/common/tvgLock.h b/thirdparty/thorvg/src/common/tvgLock.h new file mode 100644 index 000000000000..e6d993a41e53 --- /dev/null +++ b/thirdparty/thorvg/src/common/tvgLock.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2024 the ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _TVG_LOCK_H_ +#define _TVG_LOCK_H_ + +#ifdef THORVG_THREAD_SUPPORT + +#include + +namespace tvg { + + struct Key + { + std::mutex mtx; + }; + + struct ScopedLock + { + Key* key = nullptr; + + ScopedLock(Key& key) + { + key.mtx.lock(); + this->key = &key; + } + + ~ScopedLock() + { + key->mtx.unlock(); + } + }; + +} + +#else //THORVG_THREAD_SUPPORT + +namespace tvg { + + struct Key {}; + + struct ScopedLock + { + ScopedLock(Key& key) {} + }; + +} + +#endif //THORVG_THREAD_SUPPORT + +#endif //_TVG_LOCK_H_ diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp index 74f9871a0825..ab795fd90853 100644 --- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp +++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp @@ -683,32 +683,6 @@ static constexpr struct }; -static void _matrixCompose(const Matrix* m1, const Matrix* m2, Matrix* dst) -{ - auto a11 = (m1->e11 * m2->e11) + (m1->e12 * m2->e21) + (m1->e13 * m2->e31); - auto a12 = (m1->e11 * m2->e12) + (m1->e12 * m2->e22) + (m1->e13 * m2->e32); - auto a13 = (m1->e11 * m2->e13) + (m1->e12 * m2->e23) + (m1->e13 * m2->e33); - - auto a21 = (m1->e21 * m2->e11) + (m1->e22 * m2->e21) + (m1->e23 * m2->e31); - auto a22 = (m1->e21 * m2->e12) + (m1->e22 * m2->e22) + (m1->e23 * m2->e32); - auto a23 = (m1->e21 * m2->e13) + (m1->e22 * m2->e23) + (m1->e23 * m2->e33); - - auto a31 = (m1->e31 * m2->e11) + (m1->e32 * m2->e21) + (m1->e33 * m2->e31); - auto a32 = (m1->e31 * m2->e12) + (m1->e32 * m2->e22) + (m1->e33 * m2->e32); - auto a33 = (m1->e31 * m2->e13) + (m1->e32 * m2->e23) + (m1->e33 * m2->e33); - - dst->e11 = a11; - dst->e12 = a12; - dst->e13 = a13; - dst->e21 = a21; - dst->e22 = a22; - dst->e23 = a23; - dst->e31 = a31; - dst->e32 = a32; - dst->e33 = a33; -} - - /* parse transform attribute * https://www.w3.org/TR/SVG/coords.html#TransformAttribute */ @@ -751,14 +725,14 @@ static Matrix* _parseTransformationMatrix(const char* value) if (state == MatrixState::Matrix) { if (ptCount != 6) goto error; Matrix tmp = {points[0], points[2], points[4], points[1], points[3], points[5], 0, 0, 1}; - _matrixCompose(matrix, &tmp, matrix); + *matrix = mathMultiply(matrix, &tmp); } else if (state == MatrixState::Translate) { if (ptCount == 1) { Matrix tmp = {1, 0, points[0], 0, 1, 0, 0, 0, 1}; - _matrixCompose(matrix, &tmp, matrix); + *matrix = mathMultiply(matrix, &tmp); } else if (ptCount == 2) { Matrix tmp = {1, 0, points[0], 0, 1, points[1], 0, 0, 1}; - _matrixCompose(matrix, &tmp, matrix); + *matrix = mathMultiply(matrix, &tmp); } else goto error; } else if (state == MatrixState::Rotate) { //Transform to signed. @@ -768,14 +742,14 @@ static Matrix* _parseTransformationMatrix(const char* value) auto s = sinf(points[0] * (M_PI / 180.0)); if (ptCount == 1) { Matrix tmp = { c, -s, 0, s, c, 0, 0, 0, 1 }; - _matrixCompose(matrix, &tmp, matrix); + *matrix = mathMultiply(matrix, &tmp); } else if (ptCount == 3) { Matrix tmp = { 1, 0, points[1], 0, 1, points[2], 0, 0, 1 }; - _matrixCompose(matrix, &tmp, matrix); + *matrix = mathMultiply(matrix, &tmp); tmp = { c, -s, 0, s, c, 0, 0, 0, 1 }; - _matrixCompose(matrix, &tmp, matrix); + *matrix = mathMultiply(matrix, &tmp); tmp = { 1, 0, -points[1], 0, 1, -points[2], 0, 0, 1 }; - _matrixCompose(matrix, &tmp, matrix); + *matrix = mathMultiply(matrix, &tmp); } else { goto error; } @@ -785,7 +759,17 @@ static Matrix* _parseTransformationMatrix(const char* value) auto sy = sx; if (ptCount == 2) sy = points[1]; Matrix tmp = { sx, 0, 0, 0, sy, 0, 0, 0, 1 }; - _matrixCompose(matrix, &tmp, matrix); + *matrix = mathMultiply(matrix, &tmp); + } else if (state == MatrixState::SkewX) { + if (ptCount != 1) goto error; + auto deg = tanf(points[0] * (M_PI / 180.0)); + Matrix tmp = { 1, deg, 0, 0, 1, 0, 0, 0, 1 }; + *matrix = mathMultiply(matrix, &tmp); + } else if (state == MatrixState::SkewY) { + if (ptCount != 1) goto error; + auto deg = tanf(points[0] * (M_PI / 180.0)); + Matrix tmp = { 1, 0, 0, deg, 1, 0, 0, 0, 1 }; + *matrix = mathMultiply(matrix, &tmp); } } return matrix; diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp index 9a6dc459501b..049318c72826 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp @@ -257,8 +257,8 @@ static uint32_t _interpUpScaler(const uint32_t *img, TVG_UNUSED uint32_t stride, auto ry2 = ry + 1; if (ry2 >= h) ry2 = h - 1; - auto dx = static_cast((sx - rx) * 255.0f); - auto dy = static_cast((sy - ry) * 255.0f); + auto dx = static_cast((sx - rx) * 255.0f); + auto dy = static_cast((sy - ry) * 255.0f); auto c1 = img[rx + ry * w]; auto c2 = img[rx2 + ry * w]; @@ -281,21 +281,23 @@ static uint32_t _interpDownScaler(const uint32_t *img, uint32_t stride, uint32_t int32_t maxx = (int32_t)sx + n; if (maxx >= (int32_t)w) maxx = w; + int32_t inc = (n / 2) + 1; + n = 0; + auto src = img + minx + miny * stride; - for (auto y = miny; y < maxy; ++y) { + for (auto y = miny; y < maxy; y += inc) { auto p = src; - for (auto x = minx; x < maxx; ++x, ++p) { - c[0] += *p >> 24; - c[1] += (*p >> 16) & 0xff; - c[2] += (*p >> 8) & 0xff; - c[3] += *p & 0xff; + for (auto x = minx; x < maxx; x += inc, p += inc) { + c[0] += A(*p); + c[1] += C1(*p); + c[2] += C2(*p); + c[3] += C3(*p); + ++n; } - src += stride; + src += (stride * inc); } - n = (maxy - miny) * (maxx - minx); - c[0] /= n; c[1] /= n; c[2] /= n; @@ -1855,7 +1857,7 @@ void rasterUnpremultiply(Surface* surface) void rasterPremultiply(Surface* surface) { - unique_lock lock{surface->mtx}; + ScopedLock lock(surface->key); if (surface->premultiplied || (surface->channelSize != sizeof(uint32_t))) return; surface->premultiplied = true; @@ -1936,7 +1938,7 @@ bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, con bool rasterConvertCS(Surface* surface, ColorSpace to) { - unique_lock lock{surface->mtx}; + ScopedLock lock(surface->key); if (surface->cs == to) return true; //TOOD: Support SIMD accelerations diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterTexmap.h b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterTexmap.h index 8d604a3c9d7b..731f6984e3ac 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterTexmap.h +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRasterTexmap.h @@ -528,8 +528,8 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, vv = (int) v; if (vv >= sh) continue; - ar = (int)(255 * (1 - modff(u, &iptr))); - ab = (int)(255 * (1 - modff(v, &iptr))); + ar = (int)(255.0f * (1.0f - modff(u, &iptr))); + ab = (int)(255.0f * (1.0f - modff(v, &iptr))); iru = uu + 1; irv = vv + 1; @@ -576,8 +576,8 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, uu = (int) u; vv = (int) v; - ar = (int)(255 * (1 - modff(u, &iptr))); - ab = (int)(255 * (1 - modff(v, &iptr))); + ar = (int)(255.0f * (1.0f - modff(u, &iptr))); + ab = (int)(255.0f * (1.0f - modff(v, &iptr))); iru = uu + 1; irv = vv + 1; diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp index c9c543fbb58c..4645c4a58b39 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp @@ -425,6 +425,8 @@ bool SwRenderer::target(pixel_t* data, uint32_t stride, uint32_t w, uint32_t h, { if (!data || stride == 0 || w == 0 || h == 0 || w > stride) return false; + clearCompositors(); + if (!surface) surface = new SwSurface; surface->data = data; @@ -474,7 +476,6 @@ bool SwRenderer::postRender() } tasks.clear(); - clearCompositors(); return true; } diff --git a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp index e001ced2a826..45322c07b4ca 100644 --- a/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp +++ b/thirdparty/thorvg/src/renderer/sw_engine/tvgSwShape.cpp @@ -64,12 +64,16 @@ static void _outlineEnd(SwOutline& outline) { if (outline.pts.empty()) return; outline.cntrs.push(outline.pts.count - 1); + outline.closed.push(false); } static void _outlineMoveTo(SwOutline& outline, const Point* to, const Matrix* transform) { - if (outline.pts.count > 0) outline.cntrs.push(outline.pts.count - 1); + if (outline.pts.count > 0) { + outline.cntrs.push(outline.pts.count - 1); + outline.closed.push(false); + } outline.pts.push(mathTransform(to, transform)); outline.types.push(SW_CURVE_TYPE_POINT); @@ -128,7 +132,7 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* trans _outlineLineTo(*dash.outline, to, transform); } } else { - while (len > dash.curLen) { + while (len - dash.curLen > 0.0001f) { Line left, right; if (dash.curLen > 0) { len -= dash.curLen; @@ -185,7 +189,7 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct _outlineCubicTo(*dash.outline, ctrl1, ctrl2, to, transform); } } else { - while (len > dash.curLen) { + while ((len - dash.curLen) > 0.0001f) { Bezier left, right; if (dash.curLen > 0) { len -= dash.curLen; @@ -315,21 +319,6 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans dash.outline = mpoolReqDashOutline(mpool, tid); - //smart reservation - auto closeCnt = 0; - auto moveCnt = 0; - - for (auto cmd = rshape->path.cmds.data; cmd < rshape->path.cmds.end(); ++cmd) { - if (*cmd == PathCommand::Close) ++closeCnt; - else if (*cmd == PathCommand::MoveTo) ++moveCnt; - } - - //No idea exact count.... Reserve Approximitely 20x... - //OPTIMIZE: we can directly copy the path points when the close is occupied with a point. - dash.outline->pts.grow(20 * (closeCnt + ptsCnt + 1)); - dash.outline->types.grow(20 * (closeCnt + ptsCnt + 1)); - dash.outline->cntrs.grow(20 * (moveCnt + 1)); - while (cmdCnt-- > 0) { switch (*cmds) { case PathCommand::Close: { @@ -435,29 +424,9 @@ static bool _genOutline(SwShape* shape, const RenderShape* rshape, const Matrix* //No actual shape data if (cmdCnt == 0 || ptsCnt == 0) return false; - //smart reservation - auto moveCnt = 0; - auto closeCnt = 0; - - for (auto cmd = rshape->path.cmds.data; cmd < rshape->path.cmds.end(); ++cmd) { - if (*cmd == PathCommand::Close) ++closeCnt; - else if (*cmd == PathCommand::MoveTo) ++moveCnt; - } - shape->outline = mpoolReqOutline(mpool, tid); auto outline = shape->outline; - //OPTIMIZE: we can directly copy the path points when the close is occupied with a point. - outline->pts.grow(ptsCnt + closeCnt + 1); - outline->types.grow(ptsCnt + closeCnt + 1); - outline->cntrs.grow(moveCnt + 1); - - //Dash outlines are always opened. - //Only normal outlines use this information, it sholud be same to their contour counts. - outline->closed.reserve(outline->cntrs.reserved); - - memset(outline->closed.data, 0x0, sizeof(bool) * outline->closed.reserved); - //Generate Outlines while (cmdCnt-- > 0) { switch (*cmds) { diff --git a/thirdparty/thorvg/src/renderer/tvgLoader.cpp b/thirdparty/thorvg/src/renderer/tvgLoader.cpp index 628b0fa17f81..b0c631eb824c 100644 --- a/thirdparty/thorvg/src/renderer/tvgLoader.cpp +++ b/thirdparty/thorvg/src/renderer/tvgLoader.cpp @@ -24,6 +24,7 @@ #include "tvgInlist.h" #include "tvgLoader.h" +#include "tvgLock.h" #ifdef THORVG_SVG_LOADER_SUPPORT #include "tvgSvgLoader.h" @@ -65,7 +66,7 @@ uint64_t HASH_KEY(const char* data, uint64_t size) /* Internal Class Implementation */ /************************************************************************/ -static mutex mtx; +static Key key; static Inlist _activeLoaders; @@ -211,7 +212,7 @@ static LoadModule* _findByType(const string& mimeType) static LoadModule* _findFromCache(const string& path) { - unique_lock lock{mtx}; + ScopedLock lock(key); auto loader = _activeLoaders.head; @@ -231,7 +232,7 @@ static LoadModule* _findFromCache(const char* data, uint32_t size, const string& auto type = _convert(mimeType); if (type == FileType::Unknown) return nullptr; - unique_lock lock{mtx}; + ScopedLock lock(key); auto loader = _activeLoaders.head; auto key = HASH_KEY(data, size); @@ -279,7 +280,7 @@ bool LoaderMgr::retrieve(LoadModule* loader) if (!loader) return false; if (loader->close()) { { - unique_lock lock{mtx}; + ScopedLock lock(key); _activeLoaders.remove(loader); } delete(loader); @@ -298,7 +299,7 @@ LoadModule* LoaderMgr::loader(const string& path, bool* invalid) if (loader->open(path)) { loader->hashpath = strdup(path.c_str()); { - unique_lock lock{mtx}; + ScopedLock lock(key); _activeLoaders.back(loader); } return loader; @@ -340,7 +341,7 @@ LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const string& mim if (auto loader = _findByType(mimeType)) { if (loader->open(data, size, copy)) { loader->hashkey = HASH_KEY(data, size); - unique_lock lock{mtx}; + ScopedLock lock(key); _activeLoaders.back(loader); return loader; } else { @@ -356,7 +357,7 @@ LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const string& mim if (loader->open(data, size, copy)) { loader->hashkey = HASH_KEY(data, size); { - unique_lock lock{mtx}; + ScopedLock lock(key); _activeLoaders.back(loader); } return loader; @@ -379,7 +380,7 @@ LoadModule* LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, bool if (loader->open(data, w, h, copy)) { loader->hashkey = HASH_KEY((const char*)data, w * h); { - unique_lock lock{mtx}; + ScopedLock lock(key); _activeLoaders.back(loader); } return loader; diff --git a/thirdparty/thorvg/src/renderer/tvgRender.h b/thirdparty/thorvg/src/renderer/tvgRender.h index 1e70b5349403..3437f9cbff5e 100644 --- a/thirdparty/thorvg/src/renderer/tvgRender.h +++ b/thirdparty/thorvg/src/renderer/tvgRender.h @@ -23,9 +23,9 @@ #ifndef _TVG_RENDER_H_ #define _TVG_RENDER_H_ -#include #include "tvgCommon.h" #include "tvgArray.h" +#include "tvgLock.h" namespace tvg { @@ -54,7 +54,7 @@ struct Surface uint32_t* buf32; //for explicit 32bits channels uint8_t* buf8; //for explicit 8bits grayscale }; - mutex mtx; //used for thread safety + Key key; //a reserved lock for the thread safety uint32_t stride = 0; uint32_t w = 0, h = 0; ColorSpace cs = ColorSpace::Unsupported; diff --git a/thirdparty/thorvg/src/renderer/tvgShape.cpp b/thirdparty/thorvg/src/renderer/tvgShape.cpp index d083c8aa2c71..a3b92532a8de 100644 --- a/thirdparty/thorvg/src/renderer/tvgShape.cpp +++ b/thirdparty/thorvg/src/renderer/tvgShape.cpp @@ -130,11 +130,11 @@ Result Shape::appendCircle(float cx, float cy, float rx, float ry) noexcept auto ryKappa = ry * PATH_KAPPA; pImpl->grow(6, 13); - pImpl->moveTo(cx + rx, cy); + pImpl->moveTo(cx, cy - ry); + pImpl->cubicTo(cx + rxKappa, cy - ry, cx + rx, cy - ryKappa, cx + rx, cy); pImpl->cubicTo(cx + rx, cy + ryKappa, cx + rxKappa, cy + ry, cx, cy + ry); pImpl->cubicTo(cx - rxKappa, cy + ry, cx - rx, cy + ryKappa, cx - rx, cy); pImpl->cubicTo(cx - rx, cy - ryKappa, cx - rxKappa, cy - ry, cx, cy - ry); - pImpl->cubicTo(cx + rxKappa, cy - ry, cx + rx, cy - ryKappa, cx + rx, cy); pImpl->close(); return Result::Success; @@ -216,21 +216,19 @@ Result Shape::appendRect(float x, float y, float w, float h, float rx, float ry) pImpl->lineTo(x, y + h); pImpl->close(); //circle - } else if (mathEqual(rx, halfW) && mathEqual(ry, halfH)) { - return appendCircle(x + (w * 0.5f), y + (h * 0.5f), rx, ry); } else { auto hrx = rx * PATH_KAPPA; auto hry = ry * PATH_KAPPA; pImpl->grow(10, 17); - pImpl->moveTo(x + rx, y); - pImpl->lineTo(x + w - rx, y); - pImpl->cubicTo(x + w - rx + hrx, y, x + w, y + ry - hry, x + w, y + ry); + pImpl->moveTo(x + w, y + ry); pImpl->lineTo(x + w, y + h - ry); pImpl->cubicTo(x + w, y + h - ry + hry, x + w - rx + hrx, y + h, x + w - rx, y + h); pImpl->lineTo(x + rx, y + h); pImpl->cubicTo(x + rx - hrx, y + h, x, y + h - ry + hry, x, y + h - ry); pImpl->lineTo(x, y + ry); pImpl->cubicTo(x, y + ry - hry, x + rx - hrx, y, x + rx, y); + pImpl->lineTo(x + w - rx, y); + pImpl->cubicTo(x + w - rx + hrx, y, x + w, y + ry - hry, x + w, y + ry); pImpl->close(); } diff --git a/thirdparty/thorvg/src/renderer/tvgTaskScheduler.cpp b/thirdparty/thorvg/src/renderer/tvgTaskScheduler.cpp index 36d1ce1f8b09..68a3dbe97a6c 100644 --- a/thirdparty/thorvg/src/renderer/tvgTaskScheduler.cpp +++ b/thirdparty/thorvg/src/renderer/tvgTaskScheduler.cpp @@ -20,19 +20,28 @@ * SOFTWARE. */ -#include -#include -#include #include "tvgArray.h" #include "tvgInlist.h" #include "tvgTaskScheduler.h" +#ifdef THORVG_THREAD_SUPPORT + #include + #include +#endif + /************************************************************************/ /* Internal Class Implementation */ /************************************************************************/ namespace tvg { +struct TaskSchedulerImpl; +static TaskSchedulerImpl* inst = nullptr; + +#ifdef THORVG_THREAD_SUPPORT + +static thread_local bool _async = true; + struct TaskQueue { Inlist taskDeque; mutex mtx; @@ -61,7 +70,7 @@ struct TaskQueue { void complete() { { - unique_lock lock{mtx}; + lock_guard lock{mtx}; done = true; } ready.notify_all(); @@ -84,7 +93,7 @@ struct TaskQueue { void push(Task* task) { { - unique_lock lock{mtx}; + lock_guard lock{mtx}; taskDeque.back(task); } ready.notify_one(); @@ -92,25 +101,22 @@ struct TaskQueue { }; -static thread_local bool _async = true; //toggle async tasking for each thread on/off - - struct TaskSchedulerImpl { Array threads; Array taskQueues; atomic idx{0}; - TaskSchedulerImpl(unsigned threadCnt) + TaskSchedulerImpl(uint32_t threadCnt) { threads.reserve(threadCnt); taskQueues.reserve(threadCnt); - for (unsigned i = 0; i < threadCnt; ++i) { + for (uint32_t i = 0; i < threadCnt; ++i) { taskQueues.push(new TaskQueue); threads.push(new thread); } - for (unsigned i = 0; i < threadCnt; ++i) { + for (uint32_t i = 0; i < threadCnt; ++i) { *threads.data[i] = thread([&, i] { run(i); }); } } @@ -136,7 +142,7 @@ struct TaskSchedulerImpl //Thread Loop while (true) { auto success = false; - for (unsigned x = 0; x < threads.count * 2; ++x) { + for (uint32_t x = 0; x < threads.count * 2; ++x) { if (taskQueues[(i + x) % threads.count]->tryPop(&task)) { success = true; break; @@ -154,7 +160,7 @@ struct TaskSchedulerImpl if (threads.count > 0 && _async) { task->prepare(); auto i = idx++; - for (unsigned n = 0; n < threads.count; ++n) { + for (uint32_t n = 0; n < threads.count; ++n) { if (taskQueues[(i + n) % threads.count]->tryPush(task)) return; } taskQueues[i % threads.count]->push(task); @@ -163,17 +169,33 @@ struct TaskSchedulerImpl task->run(0); } } + + uint32_t threadCnt() + { + return threads.count; + } }; -} +#else //THORVG_THREAD_SUPPORT -static TaskSchedulerImpl* inst = nullptr; +static bool _async = true; + +struct TaskSchedulerImpl +{ + TaskSchedulerImpl(TVG_UNUSED uint32_t threadCnt) {} + void request(Task* task) { task->run(0); } + uint32_t threadCnt() { return 0; } +}; + +#endif //THORVG_THREAD_SUPPORT + +} //namespace /************************************************************************/ /* External Class Implementation */ /************************************************************************/ -void TaskScheduler::init(unsigned threads) +void TaskScheduler::init(uint32_t threads) { if (inst) return; inst = new TaskSchedulerImpl(threads); @@ -182,7 +204,6 @@ void TaskScheduler::init(unsigned threads) void TaskScheduler::term() { - if (!inst) return; delete(inst); inst = nullptr; } @@ -194,14 +215,15 @@ void TaskScheduler::request(Task* task) } -unsigned TaskScheduler::threads() +uint32_t TaskScheduler::threads() { - if (inst) return inst->threads.count; + if (inst) return inst->threadCnt(); return 0; } void TaskScheduler::async(bool on) { + //toggle async tasking for each thread on/off _async = on; } diff --git a/thirdparty/thorvg/src/renderer/tvgTaskScheduler.h b/thirdparty/thorvg/src/renderer/tvgTaskScheduler.h index 483e08488036..58918e88f0ef 100644 --- a/thirdparty/thorvg/src/renderer/tvgTaskScheduler.h +++ b/thirdparty/thorvg/src/renderer/tvgTaskScheduler.h @@ -25,22 +25,13 @@ #include #include + #include "tvgCommon.h" #include "tvgInlist.h" -namespace tvg -{ - -struct Task; +namespace tvg { -struct TaskScheduler -{ - static unsigned threads(); - static void init(unsigned threads); - static void term(); - static void request(Task* task); - static void async(bool on); -}; +#ifdef THORVG_THREAD_SUPPORT struct Task { @@ -86,7 +77,36 @@ struct Task friend struct TaskSchedulerImpl; }; -} +#else //THORVG_THREAD_SUPPORT + +struct Task +{ +public: + INLIST_ITEM(Task); + + virtual ~Task() = default; + void done() {} + +protected: + virtual void run(unsigned tid) = 0; + +private: + friend struct TaskSchedulerImpl; +}; + +#endif //THORVG_THREAD_SUPPORT + + +struct TaskScheduler +{ + static uint32_t threads(); + static void init(uint32_t threads); + static void term(); + static void request(Task* task); + static void async(bool on); +}; + +} //namespace #endif //_TVG_TASK_SCHEDULER_H_ diff --git a/thirdparty/thorvg/update-thorvg.sh b/thirdparty/thorvg/update-thorvg.sh index 7e7fd0591c46..4f485d092156 100755 --- a/thirdparty/thorvg/update-thorvg.sh +++ b/thirdparty/thorvg/update-thorvg.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -VERSION=0.12.1 +VERSION=0.12.3 cd thirdparty/thorvg/ || true rm -rf AUTHORS LICENSE inc/ src/ *.zip *.tar.gz tmp/