mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
sw_engine: threading optimization
make it prepare step asynchronously. Change-Id: Ifb85f01d579cf1c111558842496b93fcaef74cd9
This commit is contained in:
parent
35803e9c2b
commit
36c76ca73c
26 changed files with 186 additions and 182 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue