sw_engine: threading optimization 46/236946/6
authorHermet Park <chuneon.park@samsung.com>
Tue, 23 Jun 2020 11:12:39 +0000 (20:12 +0900)
committerHermet Park <chuneon.park@samsung.com>
Wed, 24 Jun 2020 05:35:23 +0000 (14:35 +0900)
make it prepare step asynchronously.

Change-Id: Ifb85f01d579cf1c111558842496b93fcaef74cd9

26 files changed:
src/lib/sw_engine/tvgSwCommon.h
src/lib/sw_engine/tvgSwFill.cpp
src/lib/sw_engine/tvgSwRenderer.cpp
src/lib/sw_engine/tvgSwShape.cpp
src/lib/sw_engine/tvgSwStroke.cpp
src/lib/tvgCanvasImpl.h
src/meson.build
test/testBlending.cpp
test/testBoundary.cpp
test/testCustomTransform.cpp
test/testGlShape.cpp
test/testGradientTransform.cpp
test/testLinearGradient.cpp
test/testMultiShapes.cpp
test/testPath.cpp
test/testPathCopy.cpp
test/testRadialGradient.cpp
test/testScene.cpp
test/testSceneTransform.cpp
test/testShape.cpp
test/testStress.cpp
test/testStroke.cpp
test/testStrokeLine.cpp
test/testSvg.cpp
test/testTransform.cpp
test/testUpdate.cpp

index 71af7df..9c54088 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef _TVG_SW_COMMON_H_
 #define _TVG_SW_COMMON_H_
 
+#include <future>
+#include <thread>
 #include "tvgCommon.h"
 
 #if 0
@@ -201,6 +203,16 @@ struct SwShape
 };
 
 
+struct SwTask
+{
+    SwShape shape;
+    const Shape* sdata;
+    SwSize clip;
+    const Matrix* transform;
+    RenderUpdateFlag flags;
+    future<void> prepared;
+};
+
 static inline SwPoint TO_SWPOINT(const Point* pt)
 {
     return {SwCoord(pt->x * 64), SwCoord(pt->y * 64)};
@@ -261,24 +273,24 @@ bool mathSmallCubic(SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed&
 SwFixed mathMean(SwFixed angle1, SwFixed angle2);
 
 void shapeReset(SwShape& shape);
-bool shapeGenOutline(SwShape& shape, const Shape& sdata);
-bool shapeGenRle(SwShape& shape, const Shape& sdata, const SwSize& clip, const RenderTransform* transform);
+bool shapeGenOutline(SwShape& shape, const Shape* sdata);
+bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip, const Matrix* transform);
 void shapeDelOutline(SwShape& shape);
-void shapeResetStroke(SwShape& shape, const Shape& sdata);
-bool shapeGenStrokeRle(SwShape& shape, const Shape& sdata, const SwSize& clip);
-void shapeFree(SwShape* shape);
+void shapeResetStroke(SwShape& shape, const Shape* sdata);
+bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const SwSize& clip);
+void shapeFree(SwShape& shape);
 void shapeDelStroke(SwShape& shape);
-bool shapeGenFillColors(SwShape& shape, const Fill* fill, const RenderTransform* transform, bool ctable);
-void shapeResetFill(SwShape& shape, const Fill* fill);
+bool shapeGenFillColors(SwShape& shape, const Fill* fill, const Matrix* transform, bool ctable);
+void shapeResetFill(SwShape& shape);
 void shapeDelFill(SwShape& shape);
 
-void strokeReset(SwStroke& stroke, const Shape& shape);
+void strokeReset(SwStroke& stroke, const Shape* shape);
 bool strokeParseOutline(SwStroke& stroke, const SwOutline& outline);
 SwOutline* strokeExportOutline(SwStroke& stroke);
 void strokeFree(SwStroke* stroke);
 
-bool fillGenColorTable(SwFill* fill, const Fill* fdata, const RenderTransform* transform, bool ctable);
-void fillReset(SwFill* fill, const Fill* fdata);
+bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, bool ctable);
+void fillReset(SwFill* fill);
 void fillFree(SwFill* fill);
 void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len);
 void fillFetchRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len);
index 2a9ba69..5992bca 100644 (file)
@@ -88,7 +88,7 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata)
 }
 
 
-bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const RenderTransform* transform)
+bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const Matrix* transform)
 {
     assert(fill && linear);
 
@@ -100,12 +100,12 @@ bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const RenderTran
         auto cy = (y2 - y1) * 0.5f + y1;
         auto dx = x1 - cx;
         auto dy = y1 - cy;
-        x1 = dx * transform->m.e11 + dy * transform->m.e12 + transform->m.e31;
-        y1 = dx * transform->m.e21 + dy * transform->m.e22 + transform->m.e32;
+        x1 = dx * transform->e11 + dy * transform->e12 + transform->e31;
+        y1 = dx * transform->e21 + dy * transform->e22 + transform->e32;
         dx = x2 - cx;
         dy = y2 - cy;
-        x2 = dx * transform->m.e11 + dy * transform->m.e12 + transform->m.e31;
-        y2 = dx * transform->m.e21 + dy * transform->m.e22 + transform->m.e32;
+        x2 = dx * transform->e11 + dy * transform->e12 + transform->e31;
+        y2 = dx * transform->e21 + dy * transform->e22 + transform->e32;
     }
 
     fill->linear.dx = x2 - x1;
@@ -122,7 +122,7 @@ bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const RenderTran
 }
 
 
-bool _prepareRadial(SwFill* fill, const RadialGradient* radial, const RenderTransform* transform)
+bool _prepareRadial(SwFill* fill, const RadialGradient* radial, const Matrix* transform)
 {
     assert(fill && radial);
 
@@ -131,11 +131,11 @@ bool _prepareRadial(SwFill* fill, const RadialGradient* radial, const RenderTran
     if (radius < FLT_EPSILON) return true;
 
     if (transform) {
-        auto tx = fill->radial.cx * transform->m.e11 + fill->radial.cy * transform->m.e12 + transform->m.e31;
-        auto ty = fill->radial.cx * transform->m.e21 + fill->radial.cy * transform->m.e22 + transform->m.e32;
+        auto tx = fill->radial.cx * transform->e11 + fill->radial.cy * transform->e12 + transform->e31;
+        auto ty = fill->radial.cx * transform->e21 + fill->radial.cy * transform->e22 + transform->e32;
         fill->radial.cx = tx;
         fill->radial.cy = ty;
-        radius *= transform->m.e33;
+        radius *= transform->e33;
     }
 
     fill->radial.a = radius * radius;
@@ -248,7 +248,7 @@ void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x,
 }
 
 
-bool fillGenColorTable(SwFill* fill, const Fill* fdata, const RenderTransform* transform, bool ctable)
+bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, bool ctable)
 {
     if (!fill) return false;
 
@@ -272,7 +272,7 @@ bool fillGenColorTable(SwFill* fill, const Fill* fdata, const RenderTransform* t
 }
 
 
-void fillReset(SwFill* fill, const Fill* fdata)
+void fillReset(SwFill* fill)
 {
     if (fill->ctable) {
         free(fill->ctable);
index 9a5db51..8c59029 100644 (file)
@@ -36,6 +36,7 @@ bool SwRenderer::clear()
     return rasterClear(surface);
 }
 
+
 bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h)
 {
     if (!buffer || stride == 0 || w == 0 || h == 0) return false;
@@ -48,22 +49,25 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
     return true;
 }
 
+
 bool SwRenderer::render(const Shape& sdata, void *data)
 {
-    SwShape* shape = static_cast<SwShape*>(data);
-    if (!shape) return false;
+    auto task = static_cast<SwTask*>(data);
+    if (!task) return false;
+
+    if (task->prepared.valid()) task->prepared.get();
 
     uint8_t r, g, b, a;
 
     if (auto fill = sdata.fill()) {
-        rasterGradientShape(surface, *shape, fill->id());
+        rasterGradientShape(surface, task->shape, fill->id());
     } else {
         sdata.fill(&r, &g, &b, &a);
-        if (a > 0) rasterSolidShape(surface, *shape, r, g, b, a);
+        if (a > 0) rasterSolidShape(surface, task->shape, r, g, b, a);
     }
 
     sdata.strokeColor(&r, &g, &b, &a);
-    if (a > 0) rasterStroke(surface, *shape, r, g, b, a);
+    if (a > 0) rasterStroke(surface, task->shape, r, g, b, a);
 
     return true;
 }
@@ -71,67 +75,74 @@ bool SwRenderer::render(const Shape& sdata, void *data)
 
 bool SwRenderer::dispose(const Shape& sdata, void *data)
 {
-    auto shape = static_cast<SwShape*>(data);
-    if (!shape) return true;
-    shapeFree(shape);
+    auto task = static_cast<SwTask*>(data);
+    if (!task) return true;
+    if (task->prepared.valid()) task->prepared.wait();
+    shapeFree(task->shape);
+    free(task);
     return true;
 }
 
 
 void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* transform, RenderUpdateFlag flags)
 {
-    //prepare shape data
-    auto shape = static_cast<SwShape*>(data);
-    if (!shape) {
-        shape = static_cast<SwShape*>(calloc(1, sizeof(SwShape)));
-        assert(shape);
+    //prepare task
+    auto task = static_cast<SwTask*>(data);
+    if (!task) {
+        task = static_cast<SwTask*>(calloc(1, sizeof(SwTask)));
+        if (!task) return nullptr;
     }
 
-    if (flags == RenderUpdateFlag::None) return shape;
+    if (flags == RenderUpdateFlag::None || task->prepared.valid()) return task;
 
-    //TODO: Threading
+    task->sdata = &sdata;
+    task->clip = {static_cast<SwCoord>(surface.w), static_cast<SwCoord>(surface.h)};
 
-    SwSize clip = {static_cast<SwCoord>(surface.w), static_cast<SwCoord>(surface.h)};
+    if (transform) task->transform = &transform->m;
+    else task->transform = nullptr;
 
-    //Shape
-    if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform)) {
-        shapeReset(*shape);
-        uint8_t alpha = 0;
-        sdata.fill(nullptr, nullptr, nullptr, &alpha);
-        if (alpha > 0 || sdata.fill()) {
-            if (!shapeGenRle(*shape, sdata, clip, transform)) return shape;
-        }
-    }
+    task->flags = flags;
 
-    //Fill
-    if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) {
-        auto fill = sdata.fill();
-        if (fill) {
-            auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false;
-            if (ctable) shapeResetFill(*shape, fill);
-            if (!shapeGenFillColors(*shape, fill, transform, ctable)) return shape;
-        } else {
-            shapeDelFill(*shape);
-        }
-    }
-
-    //Stroke
-    if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
-        if (sdata.strokeWidth() > FLT_EPSILON) {
-            shapeResetStroke(*shape, sdata);
+    auto asyncTask = [](SwTask* task) {
+        //Shape
+        if (task->flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform)) {
+            shapeReset(task->shape);
             uint8_t alpha = 0;
-            sdata.strokeColor(nullptr, nullptr, nullptr, &alpha);
-            if (alpha > 0) {
-                if (!shapeGenStrokeRle(*shape, sdata, clip)) return shape;
+            task->sdata->fill(nullptr, nullptr, nullptr, &alpha);
+            if (alpha > 0 || task->sdata->fill()) {
+                if (!shapeGenRle(task->shape, task->sdata, task->clip, task->transform)) return;
             }
-        } else {
-            shapeDelStroke(*shape);
         }
-    }
+        //Fill
+        if (task->flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) {
+            auto fill = task->sdata->fill();
+            if (fill) {
+                auto ctable = (task->flags & RenderUpdateFlag::Gradient) ? true : false;
+                if (ctable) shapeResetFill(task->shape);
+                if (!shapeGenFillColors(task->shape, fill, task->transform, ctable)) return;
+            } else {
+                shapeDelFill(task->shape);
+            }
+        }
+        //Stroke
+        if (task->flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
+            if (task->sdata->strokeWidth() > FLT_EPSILON) {
+                shapeResetStroke(task->shape, task->sdata);
+                uint8_t alpha = 0;
+                task->sdata->strokeColor(nullptr, nullptr, nullptr, &alpha);
+                if (alpha > 0) {
+                    if (!shapeGenStrokeRle(task->shape, task->sdata, task->clip)) return;
+                }
+            } else {
+                shapeDelStroke(task->shape);
+            }
+        }
+        shapeDelOutline(task->shape);
+    };
 
-    shapeDelOutline(*shape);
+    task->prepared = async((launch::async | launch::deferred), asyncTask, task);
 
-    return shape;
+    return task;
 }
 
 
index 22fed2c..d9a4e81 100644 (file)
@@ -231,17 +231,17 @@ static bool _checkValid(const SwOutline* outline, const SwBBox& bbox, const SwSi
 }
 
 
-static void _transformOutline(SwOutline* outline, const RenderTransform* transform)
+static void _transformOutline(SwOutline* outline, const Matrix* transform)
 {
-    assert(outline);
-
     if (!transform) return;
 
+    assert(outline);
+
     for(uint32_t i = 0; i < outline->ptsCnt; ++i) {
         auto dx = static_cast<float>(outline->pts[i].x >> 6);
         auto dy = static_cast<float>(outline->pts[i].y >> 6);
-        auto tx = dx * transform->m.e11 + dy * transform->m.e12 + transform->m.e31;
-        auto ty = dx * transform->m.e21 + dy * transform->m.e22 + transform->m.e32;
+        auto tx = dx * transform->e11 + dy * transform->e12 + transform->e31;
+        auto ty = dx * transform->e21 + dy * transform->e22 + transform->e32;
         auto pt = Point{tx, ty};
         outline->pts[i] = TO_SWPOINT(&pt);
     }
@@ -340,13 +340,15 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct
 }
 
 
-SwOutline* _genDashOutline(const Shape& shape)
+SwOutline* _genDashOutline(const Shape* sdata)
 {
+    assert(sdata);
+
     const PathCommand* cmds = nullptr;
-    auto cmdCnt = shape.pathCommands(&cmds);
+    auto cmdCnt = sdata->pathCommands(&cmds);
 
     const Point* pts = nullptr;
-    auto ptsCnt = shape.pathCoords(&pts);
+    auto ptsCnt = sdata->pathCoords(&pts);
 
     //No actual shape data
     if (cmdCnt == 0 || ptsCnt == 0) return nullptr;
@@ -359,7 +361,7 @@ SwOutline* _genDashOutline(const Shape& shape)
     dash.curOpGap = false;
 
     const float* pattern;
-    dash.cnt = shape.strokeDash(&pattern);
+    dash.cnt = sdata->strokeDash(&pattern);
     assert(dash.cnt > 0 && pattern);
 
     //Is it safe to mutual exclusive?
@@ -440,7 +442,7 @@ SwOutline* _genDashOutline(const Shape& shape)
 /* External Class Implementation                                        */
 /************************************************************************/
 
-bool shapeGenRle(SwShape& shape, const Shape& sdata, const SwSize& clip, const RenderTransform* transform)
+bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip, const Matrix* transform)
 {
     if (!shapeGenOutline(shape, sdata)) return false;
 
@@ -474,13 +476,15 @@ void shapeReset(SwShape& shape)
 }
 
 
-bool shapeGenOutline(SwShape& shape, const Shape& sdata)
+bool shapeGenOutline(SwShape& shape, const Shape* sdata)
 {
+    assert(sdata);
+
     const PathCommand* cmds = nullptr;
-    auto cmdCnt = sdata.pathCommands(&cmds);
+    auto cmdCnt = sdata->pathCommands(&cmds);
 
     const Point* pts = nullptr;
-    auto ptsCnt = sdata.pathCoords(&pts);
+    auto ptsCnt = sdata->pathCoords(&pts);
 
     //No actual shape data
     if (cmdCnt == 0 || ptsCnt == 0) return false;
@@ -559,19 +563,15 @@ bool shapeGenOutline(SwShape& shape, const Shape& sdata)
 }
 
 
-void shapeFree(SwShape* shape)
+void shapeFree(SwShape& shape)
 {
-    assert(shape);
-
-    shapeDelOutline(*shape);
-    rleFree(shape->rle);
+    shapeDelOutline(shape);
+    rleFree(shape.rle);
 
-    if (shape->stroke) {
-        rleFree(shape->strokeRle);
-        strokeFree(shape->stroke);
+    if (shape.stroke) {
+        rleFree(shape.strokeRle);
+        strokeFree(shape.stroke);
     }
-
-    free(shape);
 }
 
 
@@ -585,7 +585,7 @@ void shapeDelStroke(SwShape& shape)
 }
 
 
-void shapeResetStroke(SwShape& shape, const Shape& sdata)
+void shapeResetStroke(SwShape& shape, const Shape* sdata)
 {
     if (!shape.stroke) shape.stroke = static_cast<SwStroke*>(calloc(1, sizeof(SwStroke)));
     auto stroke = shape.stroke;
@@ -598,12 +598,14 @@ void shapeResetStroke(SwShape& shape, const Shape& sdata)
 }
 
 
-bool shapeGenStrokeRle(SwShape& shape, const Shape& sdata, const SwSize& clip)
+bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const SwSize& clip)
 {
+    assert(sdata);
+
     SwOutline* shapeOutline = nullptr;
 
     //Dash Style Stroke
-    if (sdata.strokeDash(nullptr) > 0) {
+    if (sdata->strokeDash(nullptr) > 0) {
         shapeOutline = _genDashOutline(sdata);
         if (!shapeOutline) return false;
 
@@ -633,23 +635,18 @@ bool shapeGenStrokeRle(SwShape& shape, const Shape& sdata, const SwSize& clip)
 }
 
 
-bool shapeGenFillColors(SwShape& shape, const Fill* fill, const RenderTransform* transform, bool ctable)
+bool shapeGenFillColors(SwShape& shape, const Fill* fill, const Matrix* transform, bool ctable)
 {
-    assert(fill);
-
-    fillGenColorTable(shape.fill, fill, transform, ctable);
-    return true;
+    return fillGenColorTable(shape.fill, fill, transform, ctable);
 }
 
 
-void shapeResetFill(SwShape& shape, const Fill* fill)
+void shapeResetFill(SwShape& shape)
 {
-    assert(fill);
-
     if (!shape.fill) shape.fill = static_cast<SwFill*>(calloc(1, sizeof(SwFill)));
     assert(shape.fill);
 
-    fillReset(shape.fill, fill);
+    fillReset(shape.fill);
 }
 
 
index 94a2537..6ccfb7d 100644 (file)
@@ -816,13 +816,15 @@ void strokeFree(SwStroke* stroke)
 }
 
 
-void strokeReset(SwStroke& stroke, const Shape& shape)
+void strokeReset(SwStroke& stroke, const Shape* sdata)
 {
-    stroke.width = TO_SWCOORD(shape.strokeWidth() * 0.5);
-    stroke.cap = shape.strokeCap();
+    assert(sdata);
+
+    stroke.width = TO_SWCOORD(sdata->strokeWidth() * 0.5);
+    stroke.cap = sdata->strokeCap();
 
     //Save line join: it can be temporarily changed when stroking curves...
-    stroke.joinSaved = stroke.join = shape.strokeJoin();
+    stroke.joinSaved = stroke.join = sdata->strokeJoin();
 
     stroke.borders[0].ptsCnt = 0;
     stroke.borders[0].start = -1;
index 42cf470..ae0ce3c 100644 (file)
@@ -42,7 +42,7 @@ struct Canvas::Impl
     Result push(unique_ptr<Paint> paint)
     {
         auto p = paint.release();
-        assert(p);
+        if (!p) return Result::MemoryCorruption;
         paints.push_back(p);
 
         return update(p);
@@ -50,7 +50,7 @@ struct Canvas::Impl
 
     Result clear()
     {
-        assert(renderer);
+        if (!renderer) return Result::InsufficientCondition;
 
         for (auto paint : paints) {
             if (paint->id() == PAINT_ID_SCENE) {
@@ -70,7 +70,7 @@ struct Canvas::Impl
 
     Result update()
     {
-        assert(renderer);
+        if (!renderer) return Result::InsufficientCondition;
 
         for(auto paint: paints) {
             if (paint->id() == PAINT_ID_SCENE) {
@@ -87,7 +87,7 @@ struct Canvas::Impl
 
     Result update(Paint* paint)
     {
-        assert(renderer);
+        if (!renderer) return Result::InsufficientCondition;
 
         if (paint->id() == PAINT_ID_SCENE) {
             //We know renderer type, avoid dynamic_cast for performance.
@@ -102,7 +102,7 @@ struct Canvas::Impl
 
     Result draw()
     {
-        assert(renderer);
+        if (!renderer) return Result::InsufficientCondition;
 
         //Clear render target before drawing
         if (!renderer->clear()) return Result::InsufficientCondition;
index e49c9a0..b5000bc 100644 (file)
@@ -5,10 +5,11 @@ subdir('loaders')
 subdir('examples')
 
 m_dep = meson.get_compiler('cpp').find_library('m')
+thread_dep = meson.get_compiler('cpp').find_library('pthread')
 egl_dep = meson.get_compiler('cpp').find_library('EGL')
 gles_dep = meson.get_compiler('cpp').find_library('GLESv2')
 
-tizenvg_lib_dep = [ src_dep, swengine_dep, glengine_dep, m_dep, egl_dep, gles_dep, svgloader_dep]
+tizenvg_lib_dep = [ src_dep, swengine_dep, glengine_dep, m_dep, egl_dep, gles_dep, svgloader_dep, thread_dep]
 
 
 tizenvg_lib = library(
index a5559d4..ebb3e67 100644 (file)
@@ -66,8 +66,7 @@ void tvgtest()
     tvg::Initializer::term(tvg::CanvasEngine::Sw);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
    elm_exit();
 }
index 701bb84..a71374a 100644 (file)
@@ -56,8 +56,7 @@ void tvgtest()
     tvg::Initializer::term(tvg::CanvasEngine::Sw);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
    elm_exit();
 }
index ae3d7c8..cc0c8bb 100644 (file)
@@ -96,8 +96,7 @@ void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progres
     evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
     elm_exit();
 }
index 3ff4a33..8ad43ae 100644 (file)
@@ -9,8 +9,7 @@ using namespace std;
 static Evas_GL_API *glapi;
 static unique_ptr<tvg::GlCanvas> canvas;
 
-static void
-tvgtest()
+void tvgtest()
 {
     //Create a Canvas
     canvas = tvg::GlCanvas::gen();
@@ -33,8 +32,7 @@ tvgtest()
     canvas->push(move(shape1));
 }
 
-static void
-init_gl(Evas_Object *obj)
+void init_gl(Evas_Object *obj)
 {
     //Initialize TizenVG Engine
     tvg::Initializer::init(tvg::CanvasEngine::Gl);
@@ -42,15 +40,13 @@ init_gl(Evas_Object *obj)
     tvgtest();
 }
 
-static void
-del_gl(Evas_Object *obj)
+void del_gl(Evas_Object *obj)
 {
     //Terminate TizenVG Engine
     tvg::Initializer::term(tvg::CanvasEngine::Gl);
 }
 
-static void
-draw_gl(Evas_Object *obj)
+void draw_gl(Evas_Object *obj)
 {
     Evas_GL_API *gl = elm_glview_gl_api_get(obj);
     int w, h;
@@ -66,8 +62,7 @@ draw_gl(Evas_Object *obj)
     canvas->sync();
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
     elm_exit();
 }
index 90fab16..428acc5 100644 (file)
@@ -126,8 +126,7 @@ void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progres
     evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
     elm_exit();
 }
index decf263..8016a45 100644 (file)
@@ -84,8 +84,7 @@ void tvgtest()
     tvg::Initializer::term(tvg::CanvasEngine::Sw);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
    elm_exit();
 }
index e6db3bb..9fff6f0 100644 (file)
@@ -44,8 +44,7 @@ void tvgtest()
     tvg::Initializer::term(tvg::CanvasEngine::Sw);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
    elm_exit();
 }
index 3d52003..efb784f 100644 (file)
@@ -59,8 +59,7 @@ void tvgtest()
     tvg::Initializer::term(tvg::CanvasEngine::Sw);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
    elm_exit();
 }
index 8ce33c3..4ba5941 100644 (file)
@@ -99,8 +99,7 @@ void tvgtest()
     tvg::Initializer::term(tvg::CanvasEngine::Sw);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
    elm_exit();
 }
index b50204b..e10be47 100644 (file)
@@ -84,8 +84,7 @@ void tvgtest()
     tvg::Initializer::term(tvg::CanvasEngine::Sw);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
    elm_exit();
 }
index e134237..db6fd53 100644 (file)
@@ -90,8 +90,7 @@ void tvgtest()
     tvg::Initializer::term(tvg::CanvasEngine::Sw);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
    elm_exit();
 }
index 11dade0..1e411fe 100644 (file)
@@ -120,8 +120,7 @@ void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progres
     evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
     elm_exit();
 }
index 16fc1a0..4cc1f7f 100644 (file)
@@ -38,8 +38,7 @@ void tvgtest()
     tvg::Initializer::term(tvg::CanvasEngine::Sw);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
    elm_exit();
 }
index 2c1020e..870742e 100644 (file)
@@ -3,12 +3,14 @@
 
 using namespace std;
 
-#define WIDTH 800
-#define HEIGHT 800
+#define WIDTH 1920
+#define HEIGHT 1080
 #define COUNT 50
 
 static uint32_t buffer[WIDTH * HEIGHT];
 unique_ptr<tvg::SwCanvas> canvas = nullptr;
+static double t1, t2, t3, t4;
+static unsigned cnt = 0;
 
 void tvgtest()
 {
@@ -19,20 +21,18 @@ void tvgtest()
 
 Eina_Bool anim_cb(void *data)
 {
-    static unsigned cnt = 0;
-
     //Explicitly clear all retained paint nodes.
-    double t1 = ecore_time_get();
+    t1 = ecore_time_get();
     canvas->clear();
-    double t2 = ecore_time_get();
+    t2 = ecore_time_get();
 
     for (int i = 0; i < COUNT; i++) {
         auto shape = tvg::Shape::gen();
 
-        float x = rand() % 400;
-        float y = rand() % 400;
-        float w = 1 + rand() % 600;
-        float h = 1 + rand() % 600;
+        float x = rand() % (WIDTH/2);
+        float y = rand() % (HEIGHT/2);
+        float w = 1 + rand() % 1200;
+        float h = 1 + rand() %  800;
 
         shape->appendRect(x, y, w, h, rand() % 400);
 
@@ -61,25 +61,28 @@ Eina_Bool anim_cb(void *data)
         canvas->push(move(shape));
     }
 
-    double t3 = ecore_time_get();
+    //Update Efl Canvas
+    Eo* img = (Eo*) data;
+    evas_object_image_pixels_dirty_set(img, EINA_TRUE);
+    evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT);
+
+    return ECORE_CALLBACK_RENEW;
+}
+
+void render_cb(void* data, Eo* obj)
+{
+    t3 = ecore_time_get();
 
     //Draw Next frames
     canvas->draw();
     canvas->sync();
 
-    double t4 = ecore_time_get();
-
-    printf("[%5d]: total[%fms] = clear[%fms] + update[%fms] + render[%fms]\n", ++cnt, t4 - t1, t2 - t1, t3 - t2, t4 - t3);
+    t4 = ecore_time_get();
 
-    //Update Efl Canvas
-    Eo* img = (Eo*) data;
-    evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT);
-
-    return ECORE_CALLBACK_RENEW;
+    printf("[%5d]: total[%fms] = clear[%fms], update[%fms], render[%fms]\n", ++cnt, t4 - t1, t2 - t1, t3 - t2, t4 - t3);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
     elm_exit();
 }
@@ -100,6 +103,7 @@ int main(int argc, char **argv)
     Eo* img = evas_object_image_filled_add(evas_object_evas_get(win));
     evas_object_image_size_set(img, WIDTH, HEIGHT);
     evas_object_image_data_set(img, buffer);
+    evas_object_image_pixels_get_callback_set(img, render_cb, nullptr);
     evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
     evas_object_show(img);
 
index a7ae5d0..68bffa2 100644 (file)
@@ -83,13 +83,11 @@ void tvgtest()
     tvg::Initializer::term(tvg::CanvasEngine::Sw);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
    elm_exit();
 }
 
-
 int main(int argc, char **argv)
 {
     tvgtest();
index 61e035e..3b6cc9d 100644 (file)
@@ -119,8 +119,7 @@ void tvgtest()
     tvg::Initializer::term(tvg::CanvasEngine::Sw);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
    elm_exit();
 }
index e918902..cad2f1b 100644 (file)
@@ -29,8 +29,7 @@ void tvgtest()
     tvg::Initializer::term(tvg::CanvasEngine::Sw);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
    elm_exit();
 }
index a99708d..5222743 100644 (file)
@@ -89,8 +89,7 @@ void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progres
     evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
     elm_exit();
 }
index 0ee9412..7111b21 100644 (file)
@@ -50,8 +50,7 @@ void transit_cb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progres
     evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT);
 }
 
-void
-win_del(void *data, Evas_Object *o, void *ev)
+void win_del(void *data, Evas_Object *o, void *ev)
 {
     elm_exit();
 }