From 86300c5fc05a9e0b269f2f1a624c7c1f77fd5913 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 23 Jun 2020 14:41:57 +0900 Subject: [PATCH] sw_engine: optimize raster. memset() is more than 10x faster than manual loop. Thus we replace it to manipulate buffer pixels. Change-Id: If0f255578f7d49ff6704c4f15e2eefe435cc3c15 --- meson.build | 2 +- src/lib/sw_engine/tvgSwCommon.h | 17 +++++++++++++++++ src/lib/sw_engine/tvgSwFill.cpp | 25 +------------------------ src/lib/sw_engine/tvgSwRaster.cpp | 33 +++++++++++++++++++++++++-------- src/lib/sw_engine/tvgSwRenderer.cpp | 13 ++----------- test/makefile | 0 6 files changed, 46 insertions(+), 44 deletions(-) mode change 100755 => 100644 test/makefile diff --git a/meson.build b/meson.build index 5692fbc..6693650 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project('tizenvg', 'cpp', - default_options : ['buildtype=debug', 'werror=false', 'cpp_std=c++14'], + default_options : ['buildtype=debugoptimized', 'werror=false', 'cpp_std=c++14', 'optimization=s'], version : '0.1.0', license : 'Apache-2.0') diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index eedaf9d..076cccd 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -19,6 +19,16 @@ #include "tvgCommon.h" +#if 1 +#include +static double timeStamp() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (tv.tv_sec + tv.tv_usec / 1000000.0); +} +#endif + using namespace tvg; #define SW_CURVE_TYPE_POINT 0 @@ -230,6 +240,12 @@ static inline uint32_t COLOR_ARGB_JOIN(uint8_t r, uint8_t g, uint8_t b, uint8_t } +static inline void COLOR_SET(uint32_t *dst, uint32_t val, uint32_t len) +{ + while (len--) *dst++ = val; +} + + int64_t mathMultiply(int64_t a, int64_t b); int64_t mathDivide(int64_t a, int64_t b); int64_t mathMulDiv(int64_t a, int64_t b, int64_t c); @@ -273,5 +289,6 @@ void rleFree(SwRleData* rle); bool rasterGradientShape(Surface& surface, SwShape& shape, unsigned id); bool rasterSolidShape(Surface& surface, SwShape& shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); bool rasterStroke(Surface& surface, SwShape& shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); +bool rasterClear(Surface& surface); #endif /* _TVG_SW_COMMON_H_ */ diff --git a/src/lib/sw_engine/tvgSwFill.cpp b/src/lib/sw_engine/tvgSwFill.cpp index 0bf3024..bd7f81e 100644 --- a/src/lib/sw_engine/tvgSwFill.cpp +++ b/src/lib/sw_engine/tvgSwFill.cpp @@ -181,29 +181,6 @@ static inline uint32_t _pixel(const SwFill* fill, float pos) } -static inline void _write(uint32_t *dst, uint32_t val, uint32_t len) -{ - if (len <= 0) return; - - // Cute hack to align future memcopy operation - // and do unroll the loop a bit. Not sure it is - // the most efficient, but will do for now. - auto n = (len + 7) / 8; - - switch (len & 0x07) { - case 0: do { *dst++ = val; - case 7: *dst++ = val; - case 6: *dst++ = val; - case 5: *dst++ = val; - case 4: *dst++ = val; - case 3: *dst++ = val; - case 2: *dst++ = val; - case 1: *dst++ = val; - } while (--n > 0); - } -} - - /************************************************************************/ /* External Class Implementation */ /************************************************************************/ @@ -244,7 +221,7 @@ void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, if (fabsf(inc) < FLT_EPSILON) { auto color = _fixedPixel(fill, static_cast(t * FIXPT_SIZE)); - _write(dst, color, len); + COLOR_SET(dst, color, len); return; } diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 05f23e6..05429f3 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -24,20 +24,22 @@ /* Internal Class Implementation */ /************************************************************************/ + static bool _rasterTranslucentRle(Surface& surface, SwRleData* rle, uint32_t color) { if (!rle) return false; auto span = rle->spans; auto stride = surface.stride; - uint32_t tmp; + uint32_t src; for (uint32_t i = 0; i < rle->size; ++i) { auto dst = &surface.buffer[span->y * stride + span->x]; - if (span->coverage < 255) tmp = COLOR_ALPHA_BLEND(color, span->coverage); - else tmp = color; + if (span->coverage < 255) src = COLOR_ALPHA_BLEND(color, span->coverage); + else src = color; + auto ialpha = 255 - COLOR_ALPHA(src); for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = tmp + COLOR_ALPHA_BLEND(dst[i], 255 - COLOR_ALPHA(tmp)); + dst[i] = src + COLOR_ALPHA_BLEND(dst[i], ialpha); } ++span; } @@ -55,12 +57,12 @@ static bool _rasterSolidRle(Surface& surface, SwRleData* rle, uint32_t color) for (uint32_t i = 0; i < rle->size; ++i) { auto dst = &surface.buffer[span->y * stride + span->x]; if (span->coverage == 255) { - for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = color; - } + COLOR_SET(dst, color, span->len); } else { + auto src = COLOR_ALPHA_BLEND(color, span->coverage); + auto ialpha = 255 - span->coverage; for (uint32_t i = 0; i < span->len; ++i) { - dst[i] = COLOR_ALPHA_BLEND(color, span->coverage) + COLOR_ALPHA_BLEND(dst[i], 255 - span->coverage); + dst[i] = src + COLOR_ALPHA_BLEND(dst[i], ialpha); } } ++span; @@ -188,4 +190,19 @@ bool rasterStroke(Surface& surface, SwShape& shape, uint8_t r, uint8_t g, uint8_ } +bool rasterClear(Surface& surface) +{ + if (!surface.buffer || surface.stride <= 0 || surface.w <= 0 || surface.h <= 0) return false; + + if (surface.w == surface.stride) { + COLOR_SET(surface.buffer, 0xff000000, surface.w * surface.h); + } else { + for (uint32_t i = 0; i < surface.h; i++) { + COLOR_SET(surface.buffer + surface.stride * i, 0xff000000, surface.w); + } + } + return true; +} + + #endif /* _TVG_SW_RASTER_CPP_ */ \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index adeb738..9a5db51 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -20,6 +20,7 @@ #include "tvgSwCommon.h" #include "tvgSwRenderer.h" + /************************************************************************/ /* Internal Class Implementation */ /************************************************************************/ @@ -32,17 +33,7 @@ static RenderInitializer renderInit; bool SwRenderer::clear() { - if (!surface.buffer) return false; - - assert(surface.stride > 0 && surface.w > 0 && surface.h > 0); - - //OPTIMIZE ME: SIMD! - for (uint32_t i = 0; i < surface.h; i++) { - for (uint32_t j = 0; j < surface.w; j++) - surface.buffer[surface.stride * i + j] = 0xff000000; //Solid Black - } - - return true; + return rasterClear(surface); } bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) diff --git a/test/makefile b/test/makefile old mode 100755 new mode 100644 -- 2.7.4