mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-27 08:36:59 +00:00
sw_engine: optimize rasterizey by threading it.
Also, newly introduced render interfaces: preRender(), postRender(), flush() Change-Id: If506fa27e3c7dbd89f6734cad4774c1d151b88aa
This commit is contained in:
parent
36c76ca73c
commit
4156de72f1
13 changed files with 166 additions and 66 deletions
|
@ -153,7 +153,7 @@ public:
|
||||||
virtual Result update() noexcept;
|
virtual Result update() noexcept;
|
||||||
virtual Result update(Paint* paint) noexcept;
|
virtual Result update(Paint* paint) noexcept;
|
||||||
virtual Result draw(bool async = true) noexcept;
|
virtual Result draw(bool async = true) noexcept;
|
||||||
virtual Result sync() = 0;
|
virtual Result sync() noexcept;
|
||||||
|
|
||||||
_TVG_DECLARE_ACCESSOR(Scene);
|
_TVG_DECLARE_ACCESSOR(Scene);
|
||||||
_TVG_DECLARE_PRIVATE(Canvas);
|
_TVG_DECLARE_PRIVATE(Canvas);
|
||||||
|
@ -315,7 +315,6 @@ public:
|
||||||
~SwCanvas();
|
~SwCanvas();
|
||||||
|
|
||||||
Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept;
|
Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept;
|
||||||
Result sync() noexcept override;
|
|
||||||
|
|
||||||
static std::unique_ptr<SwCanvas> gen() noexcept;
|
static std::unique_ptr<SwCanvas> gen() noexcept;
|
||||||
|
|
||||||
|
@ -337,9 +336,7 @@ public:
|
||||||
~GlCanvas();
|
~GlCanvas();
|
||||||
|
|
||||||
//TODO: Gl Specific methods. Need gl backend configuration methods as well.
|
//TODO: Gl Specific methods. Need gl backend configuration methods as well.
|
||||||
|
|
||||||
Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept;
|
Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept;
|
||||||
Result sync() noexcept override;
|
|
||||||
|
|
||||||
static std::unique_ptr<GlCanvas> gen() noexcept;
|
static std::unique_ptr<GlCanvas> gen() noexcept;
|
||||||
|
|
||||||
|
|
|
@ -53,10 +53,28 @@ bool GlRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GlRenderer::flush()
|
bool GlRenderer::flush()
|
||||||
{
|
{
|
||||||
GL_CHECK(glFinish());
|
GL_CHECK(glFinish());
|
||||||
mColorProgram->unload();
|
mColorProgram->unload();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GlRenderer::preRender()
|
||||||
|
{
|
||||||
|
//TODO: called just before render()
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GlRenderer::postRender()
|
||||||
|
{
|
||||||
|
//TODO: called just after render()
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,9 +28,11 @@ public:
|
||||||
|
|
||||||
void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) override;
|
void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) override;
|
||||||
bool dispose(const Shape& shape, void *data) override;
|
bool dispose(const Shape& shape, void *data) override;
|
||||||
|
bool preRender() override;
|
||||||
bool render(const Shape& shape, void *data) override;
|
bool render(const Shape& shape, void *data) override;
|
||||||
|
bool postRender() override;
|
||||||
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
|
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
|
||||||
void flush();
|
bool flush() override;
|
||||||
bool clear() override;
|
bool clear() override;
|
||||||
uint32_t ref() override;
|
uint32_t ref() override;
|
||||||
uint32_t unref() override;
|
uint32_t unref() override;
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
#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
|
||||||
|
@ -203,16 +201,6 @@ 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)};
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#ifndef _TVG_SW_RENDERER_CPP_
|
#ifndef _TVG_SW_RENDERER_CPP_
|
||||||
#define _TVG_SW_RENDERER_CPP_
|
#define _TVG_SW_RENDERER_CPP_
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
#include "tvgSwCommon.h"
|
#include "tvgSwCommon.h"
|
||||||
#include "tvgSwRenderer.h"
|
#include "tvgSwRenderer.h"
|
||||||
|
|
||||||
|
@ -24,19 +26,37 @@
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* Internal Class Implementation */
|
/* Internal Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
namespace tvg {
|
||||||
|
struct SwTask
|
||||||
|
{
|
||||||
|
SwShape shape;
|
||||||
|
const Shape* sdata;
|
||||||
|
SwSize clip;
|
||||||
|
const Matrix* transform;
|
||||||
|
RenderUpdateFlag flags;
|
||||||
|
future<void> progress;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static RenderInitializer renderInit;
|
static RenderInitializer renderInit;
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
bool SwRenderer::clear()
|
SwRenderer::~SwRenderer()
|
||||||
{
|
{
|
||||||
return rasterClear(surface);
|
if (progress.valid()) progress.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SwRenderer::clear()
|
||||||
|
{
|
||||||
|
if (progress.valid()) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -50,24 +70,64 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SwRenderer::preRender()
|
||||||
|
{
|
||||||
|
//before we start rendering, we should finish all preparing tasks
|
||||||
|
while (prepareTasks.size() > 0) {
|
||||||
|
auto task = prepareTasks.front();
|
||||||
|
if (task->progress.valid()) task->progress.get();
|
||||||
|
prepareTasks.pop();
|
||||||
|
renderTasks.push(task);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SwRenderer::postRender()
|
||||||
|
{
|
||||||
|
auto asyncTask = [](SwRenderer* renderer) {
|
||||||
|
renderer->doRender();
|
||||||
|
};
|
||||||
|
|
||||||
|
progress = async(launch::async, asyncTask, this);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SwRenderer::doRender()
|
||||||
|
{
|
||||||
|
rasterClear(surface);
|
||||||
|
|
||||||
|
while (renderTasks.size() > 0) {
|
||||||
|
auto task = renderTasks.front();
|
||||||
|
uint8_t r, g, b, a;
|
||||||
|
if (auto fill = task->sdata->fill()) {
|
||||||
|
rasterGradientShape(surface, task->shape, fill->id());
|
||||||
|
} else{
|
||||||
|
task->sdata->fill(&r, &g, &b, &a);
|
||||||
|
if (a > 0) rasterSolidShape(surface, task->shape, r, g, b, a);
|
||||||
|
}
|
||||||
|
task->sdata->strokeColor(&r, &g, &b, &a);
|
||||||
|
if (a > 0) rasterStroke(surface, task->shape, r, g, b, a);
|
||||||
|
renderTasks.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SwRenderer::flush()
|
||||||
|
{
|
||||||
|
if (progress.valid()) {
|
||||||
|
progress.get();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SwRenderer::render(const Shape& sdata, void *data)
|
bool SwRenderer::render(const Shape& sdata, void *data)
|
||||||
{
|
{
|
||||||
auto task = static_cast<SwTask*>(data);
|
//Do Nothing
|
||||||
if (!task) return false;
|
|
||||||
|
|
||||||
if (task->prepared.valid()) task->prepared.get();
|
|
||||||
|
|
||||||
uint8_t r, g, b, a;
|
|
||||||
|
|
||||||
if (auto fill = sdata.fill()) {
|
|
||||||
rasterGradientShape(surface, task->shape, fill->id());
|
|
||||||
} else {
|
|
||||||
sdata.fill(&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, task->shape, r, g, b, a);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -77,7 +137,7 @@ bool SwRenderer::dispose(const Shape& sdata, void *data)
|
||||||
{
|
{
|
||||||
auto task = static_cast<SwTask*>(data);
|
auto task = static_cast<SwTask*>(data);
|
||||||
if (!task) return true;
|
if (!task) return true;
|
||||||
if (task->prepared.valid()) task->prepared.wait();
|
if (task->progress.valid()) task->progress.get();
|
||||||
shapeFree(task->shape);
|
shapeFree(task->shape);
|
||||||
free(task);
|
free(task);
|
||||||
return true;
|
return true;
|
||||||
|
@ -93,7 +153,7 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform*
|
||||||
if (!task) return nullptr;
|
if (!task) return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags == RenderUpdateFlag::None || task->prepared.valid()) return task;
|
if (flags == RenderUpdateFlag::None || task->progress.valid()) return task;
|
||||||
|
|
||||||
task->sdata = &sdata;
|
task->sdata = &sdata;
|
||||||
task->clip = {static_cast<SwCoord>(surface.w), static_cast<SwCoord>(surface.h)};
|
task->clip = {static_cast<SwCoord>(surface.w), static_cast<SwCoord>(surface.h)};
|
||||||
|
@ -140,7 +200,8 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform*
|
||||||
shapeDelOutline(task->shape);
|
shapeDelOutline(task->shape);
|
||||||
};
|
};
|
||||||
|
|
||||||
task->prepared = async((launch::async | launch::deferred), asyncTask, task);
|
prepareTasks.push(task);
|
||||||
|
task->progress = async((launch::async | launch::deferred), asyncTask, task);
|
||||||
|
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,26 @@
|
||||||
#ifndef _TVG_SW_RENDERER_H_
|
#ifndef _TVG_SW_RENDERER_H_
|
||||||
#define _TVG_SW_RENDERER_H_
|
#define _TVG_SW_RENDERER_H_
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <future>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
namespace tvg
|
||||||
|
{
|
||||||
|
|
||||||
|
struct SwTask;
|
||||||
|
|
||||||
class SwRenderer : public RenderMethod
|
class SwRenderer : public RenderMethod
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Surface surface;
|
|
||||||
|
|
||||||
void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) override;
|
void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) override;
|
||||||
bool dispose(const Shape& shape, void *data) override;
|
bool dispose(const Shape& shape, void *data) override;
|
||||||
|
bool preRender() override;
|
||||||
bool render(const Shape& shape, void *data) override;
|
bool render(const Shape& shape, void *data) override;
|
||||||
|
bool postRender() override;
|
||||||
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
|
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
|
||||||
bool clear() override;
|
bool clear() override;
|
||||||
|
bool flush() override;
|
||||||
uint32_t ref() override;
|
uint32_t ref() override;
|
||||||
uint32_t unref() override;
|
uint32_t unref() override;
|
||||||
|
|
||||||
|
@ -34,9 +44,18 @@ public:
|
||||||
static int init();
|
static int init();
|
||||||
static int term();
|
static int term();
|
||||||
|
|
||||||
|
void doRender(); //Internally used for threading
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Surface surface;
|
||||||
|
future<void> progress;
|
||||||
|
queue<SwTask*> prepareTasks;
|
||||||
|
queue<SwTask*> renderTasks;
|
||||||
|
|
||||||
SwRenderer(){};
|
SwRenderer(){};
|
||||||
~SwRenderer(){};
|
~SwRenderer();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _TVG_SW_RENDERER_H_ */
|
#endif /* _TVG_SW_RENDERER_H_ */
|
||||||
|
|
|
@ -568,6 +568,8 @@ void shapeFree(SwShape& shape)
|
||||||
shapeDelOutline(shape);
|
shapeDelOutline(shape);
|
||||||
rleFree(shape.rle);
|
rleFree(shape.rle);
|
||||||
|
|
||||||
|
shapeDelFill(shape);
|
||||||
|
|
||||||
if (shape.stroke) {
|
if (shape.stroke) {
|
||||||
rleFree(shape.strokeRle);
|
rleFree(shape.strokeRle);
|
||||||
strokeFree(shape.stroke);
|
strokeFree(shape.stroke);
|
||||||
|
|
|
@ -82,4 +82,15 @@ Result Canvas::update(Paint* paint) noexcept
|
||||||
return impl->update(paint);
|
return impl->update(paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Result Canvas::sync() noexcept
|
||||||
|
{
|
||||||
|
auto impl = pImpl.get();
|
||||||
|
if (!impl) return Result::MemoryCorruption;
|
||||||
|
|
||||||
|
if (impl->renderer->flush()) return Result::Success;
|
||||||
|
|
||||||
|
return Result::InsufficientCondition;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _TVG_CANVAS_CPP_ */
|
#endif /* _TVG_CANVAS_CPP_ */
|
||||||
|
|
|
@ -52,6 +52,9 @@ struct Canvas::Impl
|
||||||
{
|
{
|
||||||
if (!renderer) return Result::InsufficientCondition;
|
if (!renderer) return Result::InsufficientCondition;
|
||||||
|
|
||||||
|
//Clear render target before drawing
|
||||||
|
if (!renderer->clear()) return Result::InsufficientCondition;
|
||||||
|
|
||||||
for (auto paint : paints) {
|
for (auto paint : paints) {
|
||||||
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.
|
||||||
|
@ -104,8 +107,7 @@ struct Canvas::Impl
|
||||||
{
|
{
|
||||||
if (!renderer) return Result::InsufficientCondition;
|
if (!renderer) return Result::InsufficientCondition;
|
||||||
|
|
||||||
//Clear render target before drawing
|
if (!renderer->preRender()) return Result::InsufficientCondition;
|
||||||
if (!renderer->clear()) return Result::InsufficientCondition;
|
|
||||||
|
|
||||||
for(auto paint: paints) {
|
for(auto paint: paints) {
|
||||||
if (paint->id() == PAINT_ID_SCENE) {
|
if (paint->id() == PAINT_ID_SCENE) {
|
||||||
|
@ -117,6 +119,9 @@ struct Canvas::Impl
|
||||||
if(!SHAPE_IMPL->render(*shape, *renderer)) return Result::InsufficientCondition;
|
if(!SHAPE_IMPL->render(*shape, *renderer)) return Result::InsufficientCondition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!renderer->postRender()) return Result::InsufficientCondition;
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -57,16 +57,6 @@ Result GlCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result GlCanvas::sync() noexcept
|
|
||||||
{
|
|
||||||
auto renderer = dynamic_cast<GlRenderer*>(Canvas::pImpl.get()->renderer);
|
|
||||||
assert(renderer);
|
|
||||||
|
|
||||||
renderer->flush();
|
|
||||||
return Result::Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unique_ptr<GlCanvas> GlCanvas::gen() noexcept
|
unique_ptr<GlCanvas> GlCanvas::gen() noexcept
|
||||||
{
|
{
|
||||||
auto canvas = unique_ptr<GlCanvas>(new GlCanvas);
|
auto canvas = unique_ptr<GlCanvas>(new GlCanvas);
|
||||||
|
|
|
@ -53,8 +53,11 @@ public:
|
||||||
virtual ~RenderMethod() {}
|
virtual ~RenderMethod() {}
|
||||||
virtual void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) = 0;
|
virtual void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) = 0;
|
||||||
virtual bool dispose(const Shape& shape, void *data) = 0;
|
virtual bool dispose(const Shape& shape, void *data) = 0;
|
||||||
|
virtual bool preRender() = 0;
|
||||||
virtual bool render(const Shape& shape, void *data) = 0;
|
virtual bool render(const Shape& shape, void *data) = 0;
|
||||||
|
virtual bool postRender() = 0;
|
||||||
virtual bool clear() = 0;
|
virtual bool clear() = 0;
|
||||||
|
virtual bool flush() = 0;
|
||||||
virtual uint32_t ref() = 0;
|
virtual uint32_t ref() = 0;
|
||||||
virtual uint32_t unref() = 0;
|
virtual uint32_t unref() = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,6 +45,7 @@ SwCanvas::~SwCanvas()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept
|
Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept
|
||||||
{
|
{
|
||||||
//We know renderer type, avoid dynamic_cast for performance.
|
//We know renderer type, avoid dynamic_cast for performance.
|
||||||
|
@ -57,12 +58,6 @@ Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result SwCanvas::sync() noexcept
|
|
||||||
{
|
|
||||||
return Result::Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unique_ptr<SwCanvas> SwCanvas::gen() noexcept
|
unique_ptr<SwCanvas> SwCanvas::gen() noexcept
|
||||||
{
|
{
|
||||||
auto canvas = unique_ptr<SwCanvas>(new SwCanvas);
|
auto canvas = unique_ptr<SwCanvas>(new SwCanvas);
|
||||||
|
|
|
@ -21,9 +21,17 @@ void tvgtest()
|
||||||
|
|
||||||
Eina_Bool anim_cb(void *data)
|
Eina_Bool anim_cb(void *data)
|
||||||
{
|
{
|
||||||
|
auto t = ecore_time_get();
|
||||||
|
|
||||||
//Explicitly clear all retained paint nodes.
|
//Explicitly clear all retained paint nodes.
|
||||||
t1 = ecore_time_get();
|
if (canvas->clear() != tvg::Result::Success)
|
||||||
canvas->clear();
|
{
|
||||||
|
//Probably, you missed sync() call before.
|
||||||
|
return ECORE_CALLBACK_RENEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
t1 = t;
|
||||||
|
|
||||||
t2 = ecore_time_get();
|
t2 = ecore_time_get();
|
||||||
|
|
||||||
for (int i = 0; i < COUNT; i++) {
|
for (int i = 0; i < COUNT; i++) {
|
||||||
|
@ -61,6 +69,11 @@ Eina_Bool anim_cb(void *data)
|
||||||
canvas->push(move(shape));
|
canvas->push(move(shape));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t3 = ecore_time_get();
|
||||||
|
|
||||||
|
//Draw Next frames
|
||||||
|
canvas->draw();
|
||||||
|
|
||||||
//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_pixels_dirty_set(img, EINA_TRUE);
|
||||||
|
@ -71,10 +84,6 @@ Eina_Bool anim_cb(void *data)
|
||||||
|
|
||||||
void render_cb(void* data, Eo* obj)
|
void render_cb(void* data, Eo* obj)
|
||||||
{
|
{
|
||||||
t3 = ecore_time_get();
|
|
||||||
|
|
||||||
//Draw Next frames
|
|
||||||
canvas->draw();
|
|
||||||
canvas->sync();
|
canvas->sync();
|
||||||
|
|
||||||
t4 = ecore_time_get();
|
t4 = ecore_time_get();
|
||||||
|
|
Loading…
Add table
Reference in a new issue