sw_engine: threading optimization

make it prepare step asynchronously.

Change-Id: Ifb85f01d579cf1c111558842496b93fcaef74cd9
This commit is contained in:
Hermet Park 2020-06-23 20:12:39 +09:00
parent 35803e9c2b
commit 36c76ca73c
26 changed files with 186 additions and 182 deletions

View file

@ -17,6 +17,8 @@
#ifndef _TVG_SW_COMMON_H_ #ifndef _TVG_SW_COMMON_H_
#define _TVG_SW_COMMON_H_ #define _TVG_SW_COMMON_H_
#include <future>
#include <thread>
#include "tvgCommon.h" #include "tvgCommon.h"
#if 0 #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) static inline SwPoint TO_SWPOINT(const Point* pt)
{ {
return {SwCoord(pt->x * 64), SwCoord(pt->y * 64)}; 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); SwFixed mathMean(SwFixed angle1, SwFixed angle2);
void shapeReset(SwShape& shape); void shapeReset(SwShape& shape);
bool shapeGenOutline(SwShape& shape, const Shape& sdata); bool shapeGenOutline(SwShape& shape, const Shape* sdata);
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);
void shapeDelOutline(SwShape& shape); void shapeDelOutline(SwShape& shape);
void shapeResetStroke(SwShape& shape, const Shape& sdata); 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);
void shapeFree(SwShape* shape); void shapeFree(SwShape& shape);
void shapeDelStroke(SwShape& shape); void shapeDelStroke(SwShape& shape);
bool shapeGenFillColors(SwShape& shape, const Fill* fill, const RenderTransform* transform, bool ctable); bool shapeGenFillColors(SwShape& shape, const Fill* fill, const Matrix* transform, bool ctable);
void shapeResetFill(SwShape& shape, const Fill* fill); void shapeResetFill(SwShape& shape);
void shapeDelFill(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); bool strokeParseOutline(SwStroke& stroke, const SwOutline& outline);
SwOutline* strokeExportOutline(SwStroke& stroke); SwOutline* strokeExportOutline(SwStroke& stroke);
void strokeFree(SwStroke* stroke); void strokeFree(SwStroke* stroke);
bool fillGenColorTable(SwFill* fill, const Fill* fdata, const RenderTransform* transform, bool ctable); bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, bool ctable);
void fillReset(SwFill* fill, const Fill* fdata); void fillReset(SwFill* fill);
void fillFree(SwFill* fill); void fillFree(SwFill* fill);
void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len); 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); void fillFetchRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len);

View 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); assert(fill && linear);
@ -100,12 +100,12 @@ bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const RenderTran
auto cy = (y2 - y1) * 0.5f + y1; auto cy = (y2 - y1) * 0.5f + y1;
auto dx = x1 - cx; auto dx = x1 - cx;
auto dy = y1 - cy; auto dy = y1 - cy;
x1 = dx * transform->m.e11 + dy * transform->m.e12 + transform->m.e31; x1 = dx * transform->e11 + dy * transform->e12 + transform->e31;
y1 = dx * transform->m.e21 + dy * transform->m.e22 + transform->m.e32; y1 = dx * transform->e21 + dy * transform->e22 + transform->e32;
dx = x2 - cx; dx = x2 - cx;
dy = y2 - cy; dy = y2 - cy;
x2 = dx * transform->m.e11 + dy * transform->m.e12 + transform->m.e31; x2 = dx * transform->e11 + dy * transform->e12 + transform->e31;
y2 = dx * transform->m.e21 + dy * transform->m.e22 + transform->m.e32; y2 = dx * transform->e21 + dy * transform->e22 + transform->e32;
} }
fill->linear.dx = x2 - x1; 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); assert(fill && radial);
@ -131,11 +131,11 @@ bool _prepareRadial(SwFill* fill, const RadialGradient* radial, const RenderTran
if (radius < FLT_EPSILON) return true; if (radius < FLT_EPSILON) return true;
if (transform) { if (transform) {
auto tx = fill->radial.cx * transform->m.e11 + fill->radial.cy * transform->m.e12 + transform->m.e31; auto tx = fill->radial.cx * transform->e11 + fill->radial.cy * transform->e12 + transform->e31;
auto ty = fill->radial.cx * transform->m.e21 + fill->radial.cy * transform->m.e22 + transform->m.e32; auto ty = fill->radial.cx * transform->e21 + fill->radial.cy * transform->e22 + transform->e32;
fill->radial.cx = tx; fill->radial.cx = tx;
fill->radial.cy = ty; fill->radial.cy = ty;
radius *= transform->m.e33; radius *= transform->e33;
} }
fill->radial.a = radius * radius; 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; 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) { if (fill->ctable) {
free(fill->ctable); free(fill->ctable);

View file

@ -36,6 +36,7 @@ bool SwRenderer::clear()
return rasterClear(surface); return rasterClear(surface);
} }
bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) 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; 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; return true;
} }
bool SwRenderer::render(const Shape& sdata, void *data) bool SwRenderer::render(const Shape& sdata, void *data)
{ {
SwShape* shape = static_cast<SwShape*>(data); auto task = static_cast<SwTask*>(data);
if (!shape) return false; if (!task) return false;
if (task->prepared.valid()) task->prepared.get();
uint8_t r, g, b, a; uint8_t r, g, b, a;
if (auto fill = sdata.fill()) { if (auto fill = sdata.fill()) {
rasterGradientShape(surface, *shape, fill->id()); rasterGradientShape(surface, task->shape, fill->id());
} else { } else {
sdata.fill(&r, &g, &b, &a); 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); 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; return true;
} }
@ -71,67 +75,74 @@ bool SwRenderer::render(const Shape& sdata, void *data)
bool SwRenderer::dispose(const Shape& sdata, void *data) bool SwRenderer::dispose(const Shape& sdata, void *data)
{ {
auto shape = static_cast<SwShape*>(data); auto task = static_cast<SwTask*>(data);
if (!shape) return true; if (!task) return true;
shapeFree(shape); if (task->prepared.valid()) task->prepared.wait();
shapeFree(task->shape);
free(task);
return true; return true;
} }
void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* transform, RenderUpdateFlag flags) void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* transform, RenderUpdateFlag flags)
{ {
//prepare shape data //prepare task
auto shape = static_cast<SwShape*>(data); auto task = static_cast<SwTask*>(data);
if (!shape) { if (!task) {
shape = static_cast<SwShape*>(calloc(1, sizeof(SwShape))); task = static_cast<SwTask*>(calloc(1, sizeof(SwTask)));
assert(shape); 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 task->flags = flags;
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;
}
}
//Fill auto asyncTask = [](SwTask* task) {
if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) { //Shape
auto fill = sdata.fill(); if (task->flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform)) {
if (fill) { shapeReset(task->shape);
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);
uint8_t alpha = 0; uint8_t alpha = 0;
sdata.strokeColor(nullptr, nullptr, nullptr, &alpha); task->sdata->fill(nullptr, nullptr, nullptr, &alpha);
if (alpha > 0) { if (alpha > 0 || task->sdata->fill()) {
if (!shapeGenStrokeRle(*shape, sdata, clip)) return shape; 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;
} }

View 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; if (!transform) return;
assert(outline);
for(uint32_t i = 0; i < outline->ptsCnt; ++i) { for(uint32_t i = 0; i < outline->ptsCnt; ++i) {
auto dx = static_cast<float>(outline->pts[i].x >> 6); auto dx = static_cast<float>(outline->pts[i].x >> 6);
auto dy = static_cast<float>(outline->pts[i].y >> 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 tx = dx * transform->e11 + dy * transform->e12 + transform->e31;
auto ty = dx * transform->m.e21 + dy * transform->m.e22 + transform->m.e32; auto ty = dx * transform->e21 + dy * transform->e22 + transform->e32;
auto pt = Point{tx, ty}; auto pt = Point{tx, ty};
outline->pts[i] = TO_SWPOINT(&pt); 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; const PathCommand* cmds = nullptr;
auto cmdCnt = shape.pathCommands(&cmds); auto cmdCnt = sdata->pathCommands(&cmds);
const Point* pts = nullptr; const Point* pts = nullptr;
auto ptsCnt = shape.pathCoords(&pts); auto ptsCnt = sdata->pathCoords(&pts);
//No actual shape data //No actual shape data
if (cmdCnt == 0 || ptsCnt == 0) return nullptr; if (cmdCnt == 0 || ptsCnt == 0) return nullptr;
@ -359,7 +361,7 @@ SwOutline* _genDashOutline(const Shape& shape)
dash.curOpGap = false; dash.curOpGap = false;
const float* pattern; const float* pattern;
dash.cnt = shape.strokeDash(&pattern); dash.cnt = sdata->strokeDash(&pattern);
assert(dash.cnt > 0 && pattern); assert(dash.cnt > 0 && pattern);
//Is it safe to mutual exclusive? //Is it safe to mutual exclusive?
@ -440,7 +442,7 @@ SwOutline* _genDashOutline(const Shape& shape)
/* External Class Implementation */ /* 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; 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; const PathCommand* cmds = nullptr;
auto cmdCnt = sdata.pathCommands(&cmds); auto cmdCnt = sdata->pathCommands(&cmds);
const Point* pts = nullptr; const Point* pts = nullptr;
auto ptsCnt = sdata.pathCoords(&pts); auto ptsCnt = sdata->pathCoords(&pts);
//No actual shape data //No actual shape data
if (cmdCnt == 0 || ptsCnt == 0) return false; 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); if (shape.stroke) {
rleFree(shape->rle); 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))); if (!shape.stroke) shape.stroke = static_cast<SwStroke*>(calloc(1, sizeof(SwStroke)));
auto stroke = shape.stroke; 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; SwOutline* shapeOutline = nullptr;
//Dash Style Stroke //Dash Style Stroke
if (sdata.strokeDash(nullptr) > 0) { if (sdata->strokeDash(nullptr) > 0) {
shapeOutline = _genDashOutline(sdata); shapeOutline = _genDashOutline(sdata);
if (!shapeOutline) return false; 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); return fillGenColorTable(shape.fill, fill, transform, ctable);
fillGenColorTable(shape.fill, fill, transform, ctable);
return true;
} }
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))); if (!shape.fill) shape.fill = static_cast<SwFill*>(calloc(1, sizeof(SwFill)));
assert(shape.fill); assert(shape.fill);
fillReset(shape.fill, fill); fillReset(shape.fill);
} }

View 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); assert(sdata);
stroke.cap = shape.strokeCap();
stroke.width = TO_SWCOORD(sdata->strokeWidth() * 0.5);
stroke.cap = sdata->strokeCap();
//Save line join: it can be temporarily changed when stroking curves... //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].ptsCnt = 0;
stroke.borders[0].start = -1; stroke.borders[0].start = -1;

View file

@ -42,7 +42,7 @@ struct Canvas::Impl
Result push(unique_ptr<Paint> paint) Result push(unique_ptr<Paint> paint)
{ {
auto p = paint.release(); auto p = paint.release();
assert(p); if (!p) return Result::MemoryCorruption;
paints.push_back(p); paints.push_back(p);
return update(p); return update(p);
@ -50,7 +50,7 @@ struct Canvas::Impl
Result clear() Result clear()
{ {
assert(renderer); if (!renderer) return Result::InsufficientCondition;
for (auto paint : paints) { for (auto paint : paints) {
if (paint->id() == PAINT_ID_SCENE) { if (paint->id() == PAINT_ID_SCENE) {
@ -70,7 +70,7 @@ struct Canvas::Impl
Result update() Result update()
{ {
assert(renderer); if (!renderer) return Result::InsufficientCondition;
for(auto paint: paints) { for(auto paint: paints) {
if (paint->id() == PAINT_ID_SCENE) { if (paint->id() == PAINT_ID_SCENE) {
@ -87,7 +87,7 @@ struct Canvas::Impl
Result update(Paint* paint) Result update(Paint* paint)
{ {
assert(renderer); if (!renderer) return Result::InsufficientCondition;
if (paint->id() == PAINT_ID_SCENE) { if (paint->id() == PAINT_ID_SCENE) {
//We know renderer type, avoid dynamic_cast for performance. //We know renderer type, avoid dynamic_cast for performance.
@ -102,7 +102,7 @@ struct Canvas::Impl
Result draw() Result draw()
{ {
assert(renderer); if (!renderer) return Result::InsufficientCondition;
//Clear render target before drawing //Clear render target before drawing
if (!renderer->clear()) return Result::InsufficientCondition; if (!renderer->clear()) return Result::InsufficientCondition;

View file

@ -5,10 +5,11 @@ subdir('loaders')
subdir('examples') subdir('examples')
m_dep = meson.get_compiler('cpp').find_library('m') 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') egl_dep = meson.get_compiler('cpp').find_library('EGL')
gles_dep = meson.get_compiler('cpp').find_library('GLESv2') 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( tizenvg_lib = library(

View file

@ -66,8 +66,7 @@ void tvgtest()
tvg::Initializer::term(tvg::CanvasEngine::Sw); tvg::Initializer::term(tvg::CanvasEngine::Sw);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }

View file

@ -56,8 +56,7 @@ void tvgtest()
tvg::Initializer::term(tvg::CanvasEngine::Sw); tvg::Initializer::term(tvg::CanvasEngine::Sw);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }

View 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); evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }

View file

@ -9,8 +9,7 @@ using namespace std;
static Evas_GL_API *glapi; static Evas_GL_API *glapi;
static unique_ptr<tvg::GlCanvas> canvas; static unique_ptr<tvg::GlCanvas> canvas;
static void void tvgtest()
tvgtest()
{ {
//Create a Canvas //Create a Canvas
canvas = tvg::GlCanvas::gen(); canvas = tvg::GlCanvas::gen();
@ -33,8 +32,7 @@ tvgtest()
canvas->push(move(shape1)); canvas->push(move(shape1));
} }
static void void init_gl(Evas_Object *obj)
init_gl(Evas_Object *obj)
{ {
//Initialize TizenVG Engine //Initialize TizenVG Engine
tvg::Initializer::init(tvg::CanvasEngine::Gl); tvg::Initializer::init(tvg::CanvasEngine::Gl);
@ -42,15 +40,13 @@ init_gl(Evas_Object *obj)
tvgtest(); tvgtest();
} }
static void void del_gl(Evas_Object *obj)
del_gl(Evas_Object *obj)
{ {
//Terminate TizenVG Engine //Terminate TizenVG Engine
tvg::Initializer::term(tvg::CanvasEngine::Gl); tvg::Initializer::term(tvg::CanvasEngine::Gl);
} }
static void void draw_gl(Evas_Object *obj)
draw_gl(Evas_Object *obj)
{ {
Evas_GL_API *gl = elm_glview_gl_api_get(obj); Evas_GL_API *gl = elm_glview_gl_api_get(obj);
int w, h; int w, h;
@ -66,8 +62,7 @@ draw_gl(Evas_Object *obj)
canvas->sync(); canvas->sync();
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }

View 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); evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }

View file

@ -84,8 +84,7 @@ void tvgtest()
tvg::Initializer::term(tvg::CanvasEngine::Sw); tvg::Initializer::term(tvg::CanvasEngine::Sw);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }

View file

@ -44,8 +44,7 @@ void tvgtest()
tvg::Initializer::term(tvg::CanvasEngine::Sw); tvg::Initializer::term(tvg::CanvasEngine::Sw);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }

View file

@ -59,8 +59,7 @@ void tvgtest()
tvg::Initializer::term(tvg::CanvasEngine::Sw); tvg::Initializer::term(tvg::CanvasEngine::Sw);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }

View file

@ -99,8 +99,7 @@ void tvgtest()
tvg::Initializer::term(tvg::CanvasEngine::Sw); tvg::Initializer::term(tvg::CanvasEngine::Sw);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }

View file

@ -84,8 +84,7 @@ void tvgtest()
tvg::Initializer::term(tvg::CanvasEngine::Sw); tvg::Initializer::term(tvg::CanvasEngine::Sw);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }

View file

@ -90,8 +90,7 @@ void tvgtest()
tvg::Initializer::term(tvg::CanvasEngine::Sw); tvg::Initializer::term(tvg::CanvasEngine::Sw);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }

View 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); evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }

View file

@ -38,8 +38,7 @@ void tvgtest()
tvg::Initializer::term(tvg::CanvasEngine::Sw); tvg::Initializer::term(tvg::CanvasEngine::Sw);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }

View file

@ -3,12 +3,14 @@
using namespace std; using namespace std;
#define WIDTH 800 #define WIDTH 1920
#define HEIGHT 800 #define HEIGHT 1080
#define COUNT 50 #define COUNT 50
static uint32_t buffer[WIDTH * HEIGHT]; static uint32_t buffer[WIDTH * HEIGHT];
unique_ptr<tvg::SwCanvas> canvas = nullptr; unique_ptr<tvg::SwCanvas> canvas = nullptr;
static double t1, t2, t3, t4;
static unsigned cnt = 0;
void tvgtest() void tvgtest()
{ {
@ -19,20 +21,18 @@ void tvgtest()
Eina_Bool anim_cb(void *data) Eina_Bool anim_cb(void *data)
{ {
static unsigned cnt = 0;
//Explicitly clear all retained paint nodes. //Explicitly clear all retained paint nodes.
double t1 = ecore_time_get(); t1 = ecore_time_get();
canvas->clear(); canvas->clear();
double t2 = ecore_time_get(); t2 = ecore_time_get();
for (int i = 0; i < COUNT; i++) { for (int i = 0; i < COUNT; i++) {
auto shape = tvg::Shape::gen(); auto shape = tvg::Shape::gen();
float x = rand() % 400; float x = rand() % (WIDTH/2);
float y = rand() % 400; float y = rand() % (HEIGHT/2);
float w = 1 + rand() % 600; float w = 1 + rand() % 1200;
float h = 1 + rand() % 600; float h = 1 + rand() % 800;
shape->appendRect(x, y, w, h, rand() % 400); shape->appendRect(x, y, w, h, rand() % 400);
@ -61,25 +61,28 @@ Eina_Bool anim_cb(void *data)
canvas->push(move(shape)); canvas->push(move(shape));
} }
double 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);
//Update Efl Canvas //Update Efl Canvas
Eo* img = (Eo*) data; Eo* img = (Eo*) data;
evas_object_image_pixels_dirty_set(img, EINA_TRUE);
evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT); evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT);
return ECORE_CALLBACK_RENEW; return ECORE_CALLBACK_RENEW;
} }
void void render_cb(void* data, Eo* obj)
win_del(void *data, Evas_Object *o, void *ev) {
t3 = ecore_time_get();
//Draw Next frames
canvas->draw();
canvas->sync();
t4 = ecore_time_get();
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)
{ {
elm_exit(); elm_exit();
} }
@ -100,6 +103,7 @@ int main(int argc, char **argv)
Eo* img = evas_object_image_filled_add(evas_object_evas_get(win)); Eo* img = evas_object_image_filled_add(evas_object_evas_get(win));
evas_object_image_size_set(img, WIDTH, HEIGHT); evas_object_image_size_set(img, WIDTH, HEIGHT);
evas_object_image_data_set(img, buffer); 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_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_show(img); evas_object_show(img);

View file

@ -83,13 +83,11 @@ void tvgtest()
tvg::Initializer::term(tvg::CanvasEngine::Sw); tvg::Initializer::term(tvg::CanvasEngine::Sw);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
tvgtest(); tvgtest();

View file

@ -119,8 +119,7 @@ void tvgtest()
tvg::Initializer::term(tvg::CanvasEngine::Sw); tvg::Initializer::term(tvg::CanvasEngine::Sw);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }

View file

@ -29,8 +29,7 @@ void tvgtest()
tvg::Initializer::term(tvg::CanvasEngine::Sw); tvg::Initializer::term(tvg::CanvasEngine::Sw);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }

View 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); evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }

View 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); evas_object_image_data_update_add(img, 0, 0, WIDTH, HEIGHT);
} }
void void win_del(void *data, Evas_Object *o, void *ev)
win_del(void *data, Evas_Object *o, void *ev)
{ {
elm_exit(); elm_exit();
} }