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_
#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);

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);
@ -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);

View 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;
task->flags = flags;
auto asyncTask = [](SwTask* task) {
//Shape
if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform)) {
shapeReset(*shape);
if (task->flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform)) {
shapeReset(task->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->sdata->fill(nullptr, nullptr, nullptr, &alpha);
if (alpha > 0 || task->sdata->fill()) {
if (!shapeGenRle(task->shape, task->sdata, task->clip, task->transform)) return;
}
}
//Fill
if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) {
auto fill = sdata.fill();
if (task->flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) {
auto fill = task->sdata->fill();
if (fill) {
auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false;
if (ctable) shapeResetFill(*shape, fill);
if (!shapeGenFillColors(*shape, fill, transform, ctable)) return shape;
auto ctable = (task->flags & RenderUpdateFlag::Gradient) ? true : false;
if (ctable) shapeResetFill(task->shape);
if (!shapeGenFillColors(task->shape, fill, task->transform, ctable)) return;
} else {
shapeDelFill(*shape);
shapeDelFill(task->shape);
}
}
//Stroke
if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
if (sdata.strokeWidth() > FLT_EPSILON) {
shapeResetStroke(*shape, sdata);
if (task->flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
if (task->sdata->strokeWidth() > FLT_EPSILON) {
shapeResetStroke(task->shape, task->sdata);
uint8_t alpha = 0;
sdata.strokeColor(nullptr, nullptr, nullptr, &alpha);
task->sdata->strokeColor(nullptr, nullptr, nullptr, &alpha);
if (alpha > 0) {
if (!shapeGenStrokeRle(*shape, sdata, clip)) return shape;
if (!shapeGenStrokeRle(task->shape, task->sdata, task->clip)) return;
}
} else {
shapeDelStroke(*shape);
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;
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);
}

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);
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;

View 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;

View 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(

View 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();
}

View 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();
}

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);
}
void
win_del(void *data, Evas_Object *o, void *ev)
void win_del(void *data, Evas_Object *o, void *ev)
{
elm_exit();
}

View 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();
}

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);
}
void
win_del(void *data, Evas_Object *o, void *ev)
void win_del(void *data, Evas_Object *o, void *ev)
{
elm_exit();
}

View 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();
}

View 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();
}

View 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();
}

View 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();
}

View 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();
}

View 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();
}

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);
}
void
win_del(void *data, Evas_Object *o, void *ev)
void win_del(void *data, Evas_Object *o, void *ev)
{
elm_exit();
}

View 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();
}

View 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();
//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
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
win_del(void *data, Evas_Object *o, void *ev)
void render_cb(void* data, Eo* obj)
{
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();
}
@ -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);

View 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();

View 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();
}

View 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();
}

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);
}
void
win_del(void *data, Evas_Object *o, void *ev)
void win_del(void *data, Evas_Object *o, void *ev)
{
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);
}
void
win_del(void *data, Evas_Object *o, void *ev)
void win_del(void *data, Evas_Object *o, void *ev)
{
elm_exit();
}