sw_engine: optimize raster. 80/236880/2
authorHermet Park <chuneon.park@samsung.com>
Tue, 23 Jun 2020 05:41:57 +0000 (14:41 +0900)
committerHermet Park <chuneon.park@samsung.com>
Tue, 23 Jun 2020 07:55:06 +0000 (16:55 +0900)
memset() is more than 10x faster than manual loop.

Thus we replace it to manipulate buffer pixels.

Change-Id: If0f255578f7d49ff6704c4f15e2eefe435cc3c15

meson.build
src/lib/sw_engine/tvgSwCommon.h
src/lib/sw_engine/tvgSwFill.cpp
src/lib/sw_engine/tvgSwRaster.cpp
src/lib/sw_engine/tvgSwRenderer.cpp
test/makefile [changed mode: 0755->0644]

index 5692fbc..6693650 100644 (file)
@@ -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')
 
index eedaf9d..076cccd 100644 (file)
 
 #include "tvgCommon.h"
 
+#if 1
+#include <sys/time.h>
+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_ */
index 0bf3024..bd7f81e 100644 (file)
@@ -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<uint32_t>(t * FIXPT_SIZE));
-        _write(dst, color, len);
+        COLOR_SET(dst, color, len);
         return;
     }
 
index 05f23e6..05429f3 100644 (file)
 /* 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
index adeb738..9a5db51 100644 (file)
@@ -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)
old mode 100755 (executable)
new mode 100644 (file)