mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-09 14:13:43 +00:00
common taskscheduler: revise functionalities.
initialization interfaces has been changed for threads count.
if you want to set concrete threads count by system, please specify thread count with it.
std threads:
tvg::Initializer::init(tvg::CanvasEngine::Sw, std:🧵:hardware_concurrency());
if your system provides designed threads info, you can use it.
efl:
tvg_engine_init(TVG_ENGINE_SW, eina_cpu_count());
I recommend to avoid max threads usage for better performance.
Change-Id: I22cfa315768f73fa941be136956cdbb2cf837c20
This commit is contained in:
parent
06cadc79f5
commit
657e6daddb
34 changed files with 387 additions and 296 deletions
|
@ -366,10 +366,8 @@ public:
|
||||||
*
|
*
|
||||||
* @see ...
|
* @see ...
|
||||||
*/
|
*/
|
||||||
static Result init(CanvasEngine engine) noexcept;
|
static Result init(CanvasEngine engine, uint32_t threads) noexcept;
|
||||||
static Result term(CanvasEngine engine) noexcept;
|
static Result term(CanvasEngine engine) noexcept;
|
||||||
static Result threads(uint32_t cnt) noexcept;
|
|
||||||
static uint32_t threads() noexcept;
|
|
||||||
|
|
||||||
_TVG_DISABLE_CTOR(Initializer);
|
_TVG_DISABLE_CTOR(Initializer);
|
||||||
};
|
};
|
||||||
|
|
|
@ -88,7 +88,7 @@ typedef struct
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* Engine API */
|
/* Engine API */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method);
|
TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method, unsigned threads);
|
||||||
TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method);
|
TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -50,13 +50,13 @@ struct _Tvg_Gradient
|
||||||
/* Engine API */
|
/* Engine API */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method) {
|
TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method, unsigned threads) {
|
||||||
Result ret = Result::Success;
|
Result ret = Result::Success;
|
||||||
|
|
||||||
if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::init(tvg::CanvasEngine::Sw);
|
if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::init(tvg::CanvasEngine::Sw, threads);
|
||||||
if (ret != Result::Success) return (Tvg_Result) ret;
|
if (ret != Result::Success) return (Tvg_Result) ret;
|
||||||
|
|
||||||
if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::init(tvg::CanvasEngine::Gl);
|
if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::init(tvg::CanvasEngine::Gl, threads);
|
||||||
return (Tvg_Result) ret;
|
return (Tvg_Result) ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,10 +64,10 @@ TVG_EXPORT Tvg_Result tvg_engine_init(unsigned engine_method) {
|
||||||
TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method) {
|
TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method) {
|
||||||
Result ret = Result::Success;
|
Result ret = Result::Success;
|
||||||
|
|
||||||
if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::init(tvg::CanvasEngine::Sw);
|
if (engine_method & TVG_ENGINE_SW) ret = tvg::Initializer::term(tvg::CanvasEngine::Sw);
|
||||||
if (ret != Result::Success) return (Tvg_Result) ret;
|
if (ret != Result::Success) return (Tvg_Result) ret;
|
||||||
|
|
||||||
if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::init(tvg::CanvasEngine::Gl);
|
if (engine_method & TVG_ENGINE_GL) ret = tvg::Initializer::term(tvg::CanvasEngine::Gl);
|
||||||
return (Tvg_Result) ret;
|
return (Tvg_Result) ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ source_file = [
|
||||||
'tvgSceneImpl.h',
|
'tvgSceneImpl.h',
|
||||||
'tvgShapePath.h',
|
'tvgShapePath.h',
|
||||||
'tvgShapeImpl.h',
|
'tvgShapeImpl.h',
|
||||||
|
'tvgTaskScheduler.h',
|
||||||
'tvgBezier.cpp',
|
'tvgBezier.cpp',
|
||||||
'tvgCanvas.cpp',
|
'tvgCanvas.cpp',
|
||||||
'tvgFill.cpp',
|
'tvgFill.cpp',
|
||||||
|
@ -35,7 +36,7 @@ source_file = [
|
||||||
'tvgScene.cpp',
|
'tvgScene.cpp',
|
||||||
'tvgShape.cpp',
|
'tvgShape.cpp',
|
||||||
'tvgSwCanvas.cpp',
|
'tvgSwCanvas.cpp',
|
||||||
'tvgTask.cpp',
|
'tvgTaskScheduler.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
common_dep = declare_dependency(
|
common_dep = declare_dependency(
|
||||||
|
|
|
@ -29,6 +29,9 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
#include "thorvg.h"
|
#include "thorvg.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -46,5 +49,6 @@ using namespace tvg;
|
||||||
#include "tvgLoaderMgr.h"
|
#include "tvgLoaderMgr.h"
|
||||||
#include "tvgRender.h"
|
#include "tvgRender.h"
|
||||||
#include "tvgPaint.h"
|
#include "tvgPaint.h"
|
||||||
|
#include "tvgTaskScheduler.h"
|
||||||
|
|
||||||
#endif //_TVG_COMMON_H_
|
#endif //_TVG_COMMON_H_
|
||||||
|
|
|
@ -35,13 +35,12 @@
|
||||||
/* Internal Class Implementation */
|
/* Internal Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
static uint32_t threadCnt = 0;
|
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
Result Initializer::init(CanvasEngine engine) noexcept
|
Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept
|
||||||
{
|
{
|
||||||
auto nonSupport = true;
|
auto nonSupport = true;
|
||||||
|
|
||||||
|
@ -63,6 +62,8 @@ Result Initializer::init(CanvasEngine engine) noexcept
|
||||||
|
|
||||||
if (!LoaderMgr::init()) return Result::Unknown;
|
if (!LoaderMgr::init()) return Result::Unknown;
|
||||||
|
|
||||||
|
TaskScheduler::init(threads);
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,21 +88,9 @@ Result Initializer::term(CanvasEngine engine) noexcept
|
||||||
|
|
||||||
if (nonSupport) return Result::NonSupport;
|
if (nonSupport) return Result::NonSupport;
|
||||||
|
|
||||||
|
TaskScheduler::term();
|
||||||
|
|
||||||
if (!LoaderMgr::term()) return Result::Unknown;
|
if (!LoaderMgr::term()) return Result::Unknown;
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result Initializer::threads(uint32_t cnt) noexcept
|
|
||||||
{
|
|
||||||
threadCnt = cnt;
|
|
||||||
|
|
||||||
return Result::Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t Initializer::threads() noexcept
|
|
||||||
{
|
|
||||||
return threadCnt;
|
|
||||||
}
|
|
|
@ -19,8 +19,8 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#ifndef _TVG_SHAPE_PATH_CPP_
|
#ifndef _TVG_SHAPE_PATH_H_
|
||||||
#define _TVG_SHAPE_PATH_CPP_
|
#define _TVG_SHAPE_PATH_H_
|
||||||
|
|
||||||
#include "tvgCommon.h"
|
#include "tvgCommon.h"
|
||||||
|
|
||||||
|
@ -139,4 +139,4 @@ struct ShapePath
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_TVG_SHAPE_PATH_CPP_
|
#endif //_TVG_SHAPE_PATH_H_
|
||||||
|
|
|
@ -1,156 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <tvgTask.h>
|
|
||||||
|
|
||||||
#include <deque>
|
|
||||||
|
|
||||||
template <typename Task>
|
|
||||||
class TaskQueue {
|
|
||||||
using lock_t = std::unique_lock<std::mutex>;
|
|
||||||
std::deque<Task> _q;
|
|
||||||
bool _done{false};
|
|
||||||
std::mutex _mutex;
|
|
||||||
std::condition_variable _ready;
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool try_pop(Task &task)
|
|
||||||
{
|
|
||||||
lock_t lock{_mutex, std::try_to_lock};
|
|
||||||
if (!lock || _q.empty()) return false;
|
|
||||||
task = std::move(_q.front());
|
|
||||||
_q.pop_front();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool try_push(Task &&task)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
lock_t lock{_mutex, std::try_to_lock};
|
|
||||||
if (!lock) return false;
|
|
||||||
_q.push_back(std::move(task));
|
|
||||||
}
|
|
||||||
_ready.notify_one();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void done()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
lock_t lock{_mutex};
|
|
||||||
_done = true;
|
|
||||||
}
|
|
||||||
_ready.notify_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pop(Task &task)
|
|
||||||
{
|
|
||||||
lock_t lock{_mutex};
|
|
||||||
while (_q.empty() && !_done) _ready.wait(lock);
|
|
||||||
if (_q.empty()) return false;
|
|
||||||
task = std::move(_q.front());
|
|
||||||
_q.pop_front();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void push(Task &&task)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
lock_t lock{_mutex};
|
|
||||||
_q.push_back(std::move(task));
|
|
||||||
}
|
|
||||||
_ready.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#include <thread>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace tvg
|
|
||||||
{
|
|
||||||
|
|
||||||
class Executor
|
|
||||||
{
|
|
||||||
const unsigned _count{std::thread::hardware_concurrency()};
|
|
||||||
std::vector<std::thread> _threads;
|
|
||||||
std::vector<TaskQueue<shared_task>> _q{_count};
|
|
||||||
std::atomic<unsigned> _index{0};
|
|
||||||
void run(unsigned i)
|
|
||||||
{
|
|
||||||
// Task Loop
|
|
||||||
shared_task task;
|
|
||||||
while (true) {
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
for (unsigned n = 0; n != _count * 2; ++n) {
|
|
||||||
if (_q[(i + n) % _count].try_pop(task)) {
|
|
||||||
success = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!success && !_q[i].pop(task)) break;
|
|
||||||
|
|
||||||
(*task)();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Executor()
|
|
||||||
{
|
|
||||||
for (unsigned n = 0; n != _count; ++n) {
|
|
||||||
_threads.emplace_back([&, n] { run(n); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
~Executor()
|
|
||||||
{
|
|
||||||
for (auto &e : _q) e.done();
|
|
||||||
|
|
||||||
for (auto &e : _threads) e.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
static Executor& instance() {
|
|
||||||
static Executor singleton;
|
|
||||||
return singleton;
|
|
||||||
}
|
|
||||||
|
|
||||||
void post(shared_task task)
|
|
||||||
{
|
|
||||||
task->prepare();
|
|
||||||
|
|
||||||
auto i = _index++;
|
|
||||||
|
|
||||||
for (unsigned n = 0; n != _count; ++n) {
|
|
||||||
if (_q[(i + n) % _count].try_push(std::move(task))) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_count > 0) {
|
|
||||||
_q[i % _count].push(std::move(task));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void async(shared_task task)
|
|
||||||
{
|
|
||||||
Executor::instance().post(std::move(task));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef _TVG_TASK_H_
|
|
||||||
#define _TVG_TASK_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <future>
|
|
||||||
|
|
||||||
namespace tvg
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
Task Interface.
|
|
||||||
Able to run a task in the thread pool. derive from the
|
|
||||||
task interface and implement run method.
|
|
||||||
|
|
||||||
To get the result call task->get() which will return immidiately if the
|
|
||||||
task is already finishd otherwise will wait till task completion.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Task
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~Task() = default;
|
|
||||||
void get() { if (_receiver.valid()) _receiver.get(); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void run() = 0;
|
|
||||||
private:
|
|
||||||
void operator()()
|
|
||||||
{
|
|
||||||
run();
|
|
||||||
_sender.set_value();
|
|
||||||
}
|
|
||||||
void prepare()
|
|
||||||
{
|
|
||||||
_sender = std::promise<void>();
|
|
||||||
_receiver = _sender.get_future();
|
|
||||||
}
|
|
||||||
friend class Executor;
|
|
||||||
|
|
||||||
std::promise<void> _sender;
|
|
||||||
std::future<void> _receiver;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
using shared_task = std::shared_ptr<Task>;
|
|
||||||
|
|
||||||
/*
|
|
||||||
async() function takes a shared task and runs it in
|
|
||||||
a thread pool asyncronously. call get() on the shared_task
|
|
||||||
to get the ressult out of the shared_task.
|
|
||||||
*/
|
|
||||||
void async(shared_task task);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //_TVG_TASK_H_
|
|
189
src/lib/tvgTaskScheduler.cpp
Normal file
189
src/lib/tvgTaskScheduler.cpp
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <deque>
|
||||||
|
#include <thread>
|
||||||
|
#include "tvgCommon.h"
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* Internal Class Implementation */
|
||||||
|
/************************************************************************/
|
||||||
|
|
||||||
|
namespace tvg {
|
||||||
|
|
||||||
|
struct TaskQueue {
|
||||||
|
deque<shared_ptr<Task>> taskDeque;
|
||||||
|
mutex mtx;
|
||||||
|
condition_variable ready;
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
bool tryPop(shared_ptr<Task> &task)
|
||||||
|
{
|
||||||
|
unique_lock<mutex> lock{mtx, try_to_lock};
|
||||||
|
if (!lock || taskDeque.empty()) return false;
|
||||||
|
task = move(taskDeque.front());
|
||||||
|
taskDeque.pop_front();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tryPush(shared_ptr<Task> &&task)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
unique_lock<mutex> lock{mtx, try_to_lock};
|
||||||
|
if (!lock) return false;
|
||||||
|
taskDeque.push_back(move(task));
|
||||||
|
}
|
||||||
|
|
||||||
|
ready.notify_one();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void complete()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
unique_lock<mutex> lock{mtx};
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
ready.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pop(shared_ptr<Task> &task)
|
||||||
|
{
|
||||||
|
unique_lock<mutex> lock{mtx};
|
||||||
|
|
||||||
|
while (taskDeque.empty() && !done) {
|
||||||
|
ready.wait(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (taskDeque.empty()) return false;
|
||||||
|
|
||||||
|
task = move(taskDeque.front());
|
||||||
|
taskDeque.pop_front();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void push(shared_ptr<Task> &&task)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
unique_lock<mutex> lock{mtx};
|
||||||
|
taskDeque.push_back(move(task));
|
||||||
|
}
|
||||||
|
|
||||||
|
ready.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class TaskSchedulerImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
unsigned threadCnt;
|
||||||
|
vector<thread> threads;
|
||||||
|
vector<TaskQueue> taskQueues{threadCnt};
|
||||||
|
atomic<unsigned> idx{0};
|
||||||
|
|
||||||
|
TaskSchedulerImpl()
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < threadCnt; ++i) {
|
||||||
|
threads.emplace_back([&, i] { run(i); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~TaskSchedulerImpl()
|
||||||
|
{
|
||||||
|
for (auto& queue : taskQueues) queue.complete();
|
||||||
|
for (auto& thread : threads) thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(unsigned i)
|
||||||
|
{
|
||||||
|
shared_ptr<Task> task;
|
||||||
|
|
||||||
|
//Thread Loop
|
||||||
|
while (true) {
|
||||||
|
auto success = false;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < threadCnt * 2; ++i) {
|
||||||
|
if (taskQueues[(i + i) % threadCnt].tryPop(task)) {
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success && !taskQueues[i].pop(task)) break;
|
||||||
|
|
||||||
|
(*task)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void request(shared_ptr<Task> task)
|
||||||
|
{
|
||||||
|
//Async
|
||||||
|
if (threadCnt > 0) {
|
||||||
|
task->prepare();
|
||||||
|
auto i = idx++;
|
||||||
|
for (unsigned n = 0; n < threadCnt; ++n) {
|
||||||
|
if (taskQueues[(i + n) % threadCnt].tryPush(move(task))) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskQueues[i % threadCnt].push(move(task));
|
||||||
|
|
||||||
|
//Sync
|
||||||
|
} else {
|
||||||
|
task->run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static TaskSchedulerImpl* inst = nullptr;
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* External Class Implementation */
|
||||||
|
/************************************************************************/
|
||||||
|
|
||||||
|
void TaskScheduler::init(unsigned threads)
|
||||||
|
{
|
||||||
|
if (inst) return;
|
||||||
|
inst = new TaskSchedulerImpl;
|
||||||
|
inst->threadCnt = threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TaskScheduler::term()
|
||||||
|
{
|
||||||
|
if (!inst) return;
|
||||||
|
delete(inst);
|
||||||
|
inst = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TaskScheduler::request(shared_ptr<Task> task)
|
||||||
|
{
|
||||||
|
if (inst) {
|
||||||
|
inst->request(move(task));
|
||||||
|
}
|
||||||
|
}
|
72
src/lib/tvgTaskScheduler.h
Normal file
72
src/lib/tvgTaskScheduler.h
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef _TVG_TASK_SCHEDULER_H_
|
||||||
|
#define _TVG_TASK_SCHEDULER_H_
|
||||||
|
|
||||||
|
#include "tvgCommon.h"
|
||||||
|
|
||||||
|
namespace tvg
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Task
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::promise<void> sender;
|
||||||
|
std::future<void> receiver;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~Task() = default;
|
||||||
|
|
||||||
|
void get()
|
||||||
|
{
|
||||||
|
if (receiver.valid()) receiver.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void run() = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void operator()()
|
||||||
|
{
|
||||||
|
run();
|
||||||
|
sender.set_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepare()
|
||||||
|
{
|
||||||
|
sender = std::promise<void>();
|
||||||
|
receiver = sender.get_future();
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class TaskSchedulerImpl;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TaskScheduler
|
||||||
|
{
|
||||||
|
static void init(unsigned threads);
|
||||||
|
static void term();
|
||||||
|
static void request(shared_ptr<Task> task);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //_TVG_TASK_SCHEDULER_H_
|
|
@ -148,8 +148,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -151,8 +151,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -131,8 +131,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -120,8 +120,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ static uint32_t buffer[WIDTH * HEIGHT];
|
||||||
|
|
||||||
void testCapi()
|
void testCapi()
|
||||||
{
|
{
|
||||||
tvg_engine_init(TVG_ENGINE_SW | TVG_ENGINE_GL);
|
tvg_engine_init(TVG_ENGINE_SW | TVG_ENGINE_GL, 0);
|
||||||
|
|
||||||
Tvg_Canvas* canvas = tvg_swcanvas_create();
|
Tvg_Canvas* canvas = tvg_swcanvas_create();
|
||||||
tvg_swcanvas_set_target(canvas, buffer, WIDTH, WIDTH, HEIGHT, TVG_COLORSPACE_ARGB8888);
|
tvg_swcanvas_set_target(canvas, buffer, WIDTH, WIDTH, HEIGHT, TVG_COLORSPACE_ARGB8888);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
#include <Elementary.h>
|
#include <Elementary.h>
|
||||||
#include <thorvg.h>
|
#include <thorvg.h>
|
||||||
|
|
||||||
|
|
|
@ -176,8 +176,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -139,8 +139,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -204,31 +204,34 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
Elm_Transit *transit = elm_transit_add();
|
Elm_Transit *transit = elm_transit_add();
|
||||||
|
|
||||||
if (tvgEngine == tvg::CanvasEngine::Sw) {
|
if (tvgEngine == tvg::CanvasEngine::Sw) {
|
||||||
auto view = createSwView();
|
auto view = createSwView();
|
||||||
elm_transit_effect_add(transit, transitSwCb, view, nullptr);
|
elm_transit_effect_add(transit, transitSwCb, view, nullptr);
|
||||||
} else {
|
} else {
|
||||||
auto view = createGlView();
|
auto view = createGlView();
|
||||||
elm_transit_effect_add(transit, transitGlCb, view, nullptr);
|
elm_transit_effect_add(transit, transitGlCb, view, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
elm_transit_duration_set(transit, 2);
|
elm_transit_duration_set(transit, 2);
|
||||||
elm_transit_repeat_times_set(transit, -1);
|
elm_transit_repeat_times_set(transit, -1);
|
||||||
elm_transit_auto_reverse_set(transit, EINA_TRUE);
|
elm_transit_auto_reverse_set(transit, EINA_TRUE);
|
||||||
elm_transit_go(transit);
|
elm_transit_go(transit);
|
||||||
|
|
||||||
elm_run();
|
elm_run();
|
||||||
elm_shutdown();
|
elm_shutdown();
|
||||||
|
|
||||||
//Terminate ThorVG Engine
|
//Terminate ThorVG Engine
|
||||||
tvg::Initializer::term(tvgEngine);
|
tvg::Initializer::term(tvgEngine);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
cout << "engine is not supported" << endl;
|
cout << "engine is not supported" << endl;
|
||||||
|
|
|
@ -149,8 +149,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -109,8 +109,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -126,8 +126,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -163,8 +163,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -149,8 +149,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -156,8 +156,12 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -200,8 +200,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -99,8 +99,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -146,8 +146,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -183,8 +183,12 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -141,8 +141,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -124,8 +124,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -167,8 +167,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -128,8 +128,11 @@ int main(int argc, char **argv)
|
||||||
cout << "tvg engine: opengl" << endl;
|
cout << "tvg engine: opengl" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Threads Count
|
||||||
|
auto threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
//Initialize ThorVG Engine
|
//Initialize ThorVG Engine
|
||||||
if (tvg::Initializer::init(tvgEngine) == tvg::Result::Success) {
|
if (tvg::Initializer::init(tvgEngine, threads) == tvg::Result::Success) {
|
||||||
|
|
||||||
elm_init(argc, argv);
|
elm_init(argc, argv);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue