mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-23 22:58:44 +00:00
api: revise engine initialization and termination
Simplified parameters and ensured proper backend engine initialization by using reference checking through canvas instances. C++ API Modification: - Result Initializer::init(uint32_t threads, CanvasEngine engine) -> Result Initializer::init(uint32_t threads) - Result Initializer::term(CanvasEngine engine) -> Result Initializer::term() C API Modification: - Tvg_Result tvg_engine_init(Tvg_Engine engine_method, unsigned threads) -> Tvg_Result tvg_engine_init(unsigned threads); - Tvg_Result tvg_engine_term(Tvg_Engine engine_method) -> Tvg_Result tvg_engine_term() issue: https://github.com/thorvg/thorvg/issues/3116
This commit is contained in:
parent
4cf68b75e5
commit
53e5e783b7
25 changed files with 313 additions and 459 deletions
|
@ -268,7 +268,7 @@ float progress(uint32_t elapsed, float durationInSec)
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
tvg_engine_init(Tvg_Engine(TVG_ENGINE_SW), 0);
|
||||
tvg_engine_init(4);
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
|
@ -333,7 +333,7 @@ int main(int argc, char **argv)
|
|||
|
||||
SDL_Quit();
|
||||
|
||||
tvg_engine_term(Tvg_Engine(TVG_ENGINE_SW));
|
||||
tvg_engine_term();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -148,10 +148,9 @@ struct Window
|
|||
bool clearBuffer = false;
|
||||
bool print = false;
|
||||
|
||||
Window(tvg::CanvasEngine engine, Example* example, uint32_t width, uint32_t height, uint32_t threadsCnt)
|
||||
Window(Example* example, uint32_t width, uint32_t height, uint32_t threadsCnt)
|
||||
{
|
||||
//Initialize ThorVG Engine (engine: raster method)
|
||||
if (!verify(tvg::Initializer::init(threadsCnt, engine), "Failed to init ThorVG engine!")) return;
|
||||
if (!verify(tvg::Initializer::init(threadsCnt), "Failed to init ThorVG engine!")) return;
|
||||
|
||||
//Initialize the SDL
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
@ -284,7 +283,7 @@ struct Window
|
|||
|
||||
struct SwWindow : Window
|
||||
{
|
||||
SwWindow(Example* example, uint32_t width, uint32_t height, uint32_t threadsCnt) : Window(tvg::CanvasEngine::Sw, example, width, height, threadsCnt)
|
||||
SwWindow(Example* example, uint32_t width, uint32_t height, uint32_t threadsCnt) : Window(example, width, height, threadsCnt)
|
||||
{
|
||||
if (!initialized) return;
|
||||
|
||||
|
@ -323,7 +322,7 @@ struct GlWindow : Window
|
|||
{
|
||||
SDL_GLContext context;
|
||||
|
||||
GlWindow(Example* example, uint32_t width, uint32_t height, uint32_t threadsCnt) : Window(tvg::CanvasEngine::Gl, example, width, height, threadsCnt)
|
||||
GlWindow(Example* example, uint32_t width, uint32_t height, uint32_t threadsCnt) : Window(example, width, height, threadsCnt)
|
||||
{
|
||||
if (!initialized) return;
|
||||
|
||||
|
@ -383,7 +382,7 @@ struct WgWindow : Window
|
|||
WGPUAdapter adapter;
|
||||
WGPUDevice device;
|
||||
|
||||
WgWindow(Example* example, uint32_t width, uint32_t height, uint32_t threadsCnt) : Window(tvg::CanvasEngine::Wg, example, width, height, threadsCnt)
|
||||
WgWindow(Example* example, uint32_t width, uint32_t height, uint32_t threadsCnt) : Window(example, width, height, threadsCnt)
|
||||
{
|
||||
if (!initialized) return;
|
||||
|
||||
|
@ -484,7 +483,7 @@ struct WgWindow : Window
|
|||
#else
|
||||
struct WgWindow : Window
|
||||
{
|
||||
WgWindow(Example* example, uint32_t width, uint32_t height, uint32_t threadsCnt) : Window(tvg::CanvasEngine::Wg, example, width, height, threadsCnt)
|
||||
WgWindow(Example* example, uint32_t width, uint32_t height, uint32_t threadsCnt) : Window(example, width, height, threadsCnt)
|
||||
{
|
||||
cout << "webgpu driver is not detected!" << endl;
|
||||
}
|
||||
|
@ -540,20 +539,20 @@ bool verify(tvg::Result result, string failMsg)
|
|||
|
||||
int main(Example* example, int argc, char **argv, bool clearBuffer = false, uint32_t width = 800, uint32_t height = 800, uint32_t threadsCnt = 4, bool print = false)
|
||||
{
|
||||
auto engine = tvg::CanvasEngine::Sw;
|
||||
auto engine = 0; //0: sw, 1: gl, 2: wg
|
||||
|
||||
if (argc > 1) {
|
||||
if (!strcmp(argv[1], "gl")) engine = tvg::CanvasEngine::Gl;
|
||||
if (!strcmp(argv[1], "wg")) engine = tvg::CanvasEngine::Wg;
|
||||
if (!strcmp(argv[1], "gl")) engine = 1;
|
||||
if (!strcmp(argv[1], "wg")) engine = 2;
|
||||
}
|
||||
|
||||
unique_ptr<Window> window;
|
||||
|
||||
if (engine == tvg::CanvasEngine::Sw) {
|
||||
if (engine == 0) {
|
||||
window = unique_ptr<Window>(new SwWindow(example, width, height, threadsCnt));
|
||||
} else if (engine == tvg::CanvasEngine::Gl) {
|
||||
} else if (engine == 1) {
|
||||
window = unique_ptr<Window>(new GlWindow(example, width, height, threadsCnt));
|
||||
} else if (engine == tvg::CanvasEngine::Wg) {
|
||||
} else if (engine == 2) {
|
||||
window = unique_ptr<Window>(new WgWindow(example, width, height, threadsCnt));
|
||||
}
|
||||
|
||||
|
|
|
@ -401,20 +401,20 @@ void runWg()
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
auto engine = tvg::CanvasEngine::Sw;
|
||||
auto engine = 0; //0: sw, 1: gl, 2: wg
|
||||
|
||||
if (argc > 1) {
|
||||
if (!strcmp(argv[1], "gl")) engine = tvg::CanvasEngine::Gl;
|
||||
if (!strcmp(argv[1], "wg")) engine = tvg::CanvasEngine::Wg;
|
||||
if (!strcmp(argv[1], "gl")) engine = 1;
|
||||
if (!strcmp(argv[1], "wg")) engine = 2;
|
||||
}
|
||||
|
||||
if (tvgexam::verify(tvg::Initializer::init(4, engine))) {
|
||||
if (tvgexam::verify(tvg::Initializer::init(4))) {
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
if (engine == tvg::CanvasEngine::Sw) runSw();
|
||||
else if (engine == tvg::CanvasEngine::Gl) runGl();
|
||||
else if (engine == tvg::CanvasEngine::Wg) runWg();
|
||||
if (engine == 0) runSw();
|
||||
else if (engine == 1) runGl();
|
||||
else if (engine == 2) runWg();
|
||||
|
||||
SDL_Quit();
|
||||
|
||||
|
|
44
inc/thorvg.h
44
inc/thorvg.h
|
@ -237,18 +237,6 @@ enum class SceneEffect : uint8_t
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enumeration specifying the engine type used for the graphics backend. For multiple backends bitwise operation is allowed.
|
||||
*/
|
||||
enum class CanvasEngine : uint8_t
|
||||
{
|
||||
All = 0, ///< All feasible rasterizers. @since 1.0
|
||||
Sw = (1 << 1), ///< CPU rasterizer.
|
||||
Gl = (1 << 2), ///< OpenGL rasterizer.
|
||||
Wg = (1 << 3), ///< WebGPU rasterizer. @since 0.15
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enumeration specifying the ThorVG class type value.
|
||||
*
|
||||
|
@ -1850,35 +1838,33 @@ class TVG_API Initializer final
|
|||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Initializes TVG engines.
|
||||
* @brief Initializes the ThorVG engine.
|
||||
*
|
||||
* TVG requires the running-engine environment.
|
||||
* TVG runs its own task-scheduler for parallelizing rendering tasks efficiently.
|
||||
* You can indicate the number of threads, the count of which is designated @p threads.
|
||||
* In the initialization step, TVG will generate/spawn the threads as set by @p threads count.
|
||||
* ThorVG requires an active runtime environment to operate.
|
||||
* Internally, it utilizes a task scheduler to efficiently parallelize rendering operations.
|
||||
* You can specify the number of worker threads using the @p threads parameter.
|
||||
* During initialization, ThorVG will spawn the specified number of threads.
|
||||
*
|
||||
* @param[in] threads The number of additional threads. Zero indicates only the main thread is to be used.
|
||||
* @param[in] engine The engine types to initialize. This is relative to the Canvas types, in which it will be used. For multiple backends bitwise operation is allowed.
|
||||
* @param[in] threads The number of worker threads to create. A value of zero indicates that only the main thread will be used.
|
||||
*
|
||||
* @retval Result::NonSupport In case the engine type is not supported on the system.
|
||||
*
|
||||
* @note The Initializer keeps track of the number of times it was called. Threads count is fixed at the first init() call.
|
||||
* @note The initializer uses internal reference counting to track multiple calls.
|
||||
* The number of threads is fixed on the first call to init() and cannot be changed in subsequent calls.
|
||||
* @see Initializer::term()
|
||||
*/
|
||||
static Result init(uint32_t threads, CanvasEngine engine = tvg::CanvasEngine::All) noexcept;
|
||||
static Result init(uint32_t threads) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Terminates TVG engines.
|
||||
* @brief Terminates the ThorVG engine.
|
||||
*
|
||||
* @param[in] engine The engine types to terminate. This is relative to the Canvas types, in which it will be used. For multiple backends bitwise operation is allowed
|
||||
* Cleans up resources and stops any internal threads initialized by init().
|
||||
*
|
||||
* @retval Result::InsufficientCondition In case there is nothing to be terminated.
|
||||
* @retval Result::NonSupport In case the engine type is not supported on the system.
|
||||
* @retval Result::InsufficientCondition Returned if there is nothing to terminate (e.g., init() was not called).
|
||||
*
|
||||
* @note Initializer does own reference counting for multiple calls.
|
||||
* @note The initializer maintains a reference count for safe repeated use.
|
||||
* Only the final call to term() will fully shut down the engine.
|
||||
* @see Initializer::init()
|
||||
*/
|
||||
static Result term(CanvasEngine engine = tvg::CanvasEngine::All) noexcept;
|
||||
static Result term() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the version of the TVG engine.
|
||||
|
|
|
@ -107,18 +107,6 @@ typedef struct _Tvg_Animation Tvg_Animation;
|
|||
typedef struct _Tvg_Accessor Tvg_Accessor;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enumeration specifying the engine type used for the graphics backend. For multiple backends bitwise operation is allowed.
|
||||
*
|
||||
* @ingroup ThorVGCapi_Initializer
|
||||
*/
|
||||
typedef enum {
|
||||
TVG_ENGINE_SW = (1 << 1), ///< CPU rasterizer
|
||||
TVG_ENGINE_GL = (1 << 2), ///< OpenGL rasterizer
|
||||
TVG_ENGINE_WG = (1 << 3) ///< WebGPU rasterizer
|
||||
} Tvg_Engine;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enumeration specifying the result from the APIs.
|
||||
*
|
||||
|
@ -342,43 +330,36 @@ typedef struct
|
|||
/* Engine API */
|
||||
/************************************************************************/
|
||||
/*!
|
||||
* @brief Initializes TVG engines.
|
||||
* @brief Initializes the ThorVG engine.
|
||||
*
|
||||
* TVG requires the running-engine environment.
|
||||
* TVG runs its own task-scheduler for parallelizing rendering tasks efficiently.
|
||||
* You can indicate the number of threads, the count of which is designated @p threads.
|
||||
* In the initialization step, TVG will generate/spawn the threads as set by @p threads count.
|
||||
* ThorVG requires an active runtime environment to operate.
|
||||
* Internally, it utilizes a task scheduler to efficiently parallelize rendering operations.
|
||||
* You can specify the number of worker threads using the @p threads parameter.
|
||||
* During initialization, ThorVG will spawn the specified number of threads.
|
||||
*
|
||||
* @param[in] engine_method The engine types to initialize. This is relative to the Canvas types, in which it will be used. For multiple backends bitwise operation is allowed.
|
||||
* @param[in] threads The number of additional threads used to perform rendering. Zero indicates only the main thread is to be used.
|
||||
* @param[in] threads The number of worker threads to create. A value of zero indicates that only the main thread will be used.
|
||||
*
|
||||
* @return Tvg_Result enumeration.
|
||||
* @retval TVG_RESULT_INVALID_ARGUMENT Unknown engine type.
|
||||
* @retval TVG_RESULT_NOT_SUPPORTED Unsupported engine type.
|
||||
*
|
||||
* @note The Initializer keeps track of the number of times it was called. Threads count is fixed at the first init() call.
|
||||
* @note The initializer uses internal reference counting to track multiple calls.
|
||||
* The number of threads is fixed on the first call to tvg_engine_init() and cannot be changed in subsequent calls.
|
||||
* @see tvg_engine_term()
|
||||
* @see Tvg_Engine
|
||||
*/
|
||||
TVG_API Tvg_Result tvg_engine_init(Tvg_Engine engine_method, unsigned threads);
|
||||
TVG_API Tvg_Result tvg_engine_init(unsigned threads);
|
||||
|
||||
|
||||
/*!
|
||||
* @brief Terminates TVG engines.
|
||||
* @brief Terminates the ThorVG engine.
|
||||
*
|
||||
* It should be called in case of termination of the TVG client with the same engine types as were passed when tvg_engine_init() was called.
|
||||
*
|
||||
* @param engine_method The engine types to terminate. This is relative to the Canvas types, in which it will be used. For multiple backends bitwise operation is allowed
|
||||
* Cleans up resources and stops any internal threads initialized by tvg_engine_init().
|
||||
*
|
||||
* @return Tvg_Result enumeration.
|
||||
* @retval TVG_RESULT_INSUFFICIENT_CONDITION Nothing to be terminated.
|
||||
* @retval TVG_RESULT_INVALID_ARGUMENT Unknown engine type.
|
||||
* @retval TVG_RESULT_NOT_SUPPORTED Unsupported engine type.
|
||||
* @retval TVG_RESULT_INSUFFICIENT_CONDITION Returned if there is nothing to terminate (e.g., tvg_engine_init() was not called).
|
||||
*
|
||||
* @note The initializer maintains a reference count for safe repeated use. Only the final call to tvg_engine_term() will fully shut down the engine.
|
||||
* @see tvg_engine_init()
|
||||
* @see Tvg_Engine
|
||||
*/
|
||||
TVG_API Tvg_Result tvg_engine_term(Tvg_Engine engine_method);
|
||||
TVG_API Tvg_Result tvg_engine_term();
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,15 +40,15 @@ extern "C" {
|
|||
/* Engine API */
|
||||
/************************************************************************/
|
||||
|
||||
TVG_API Tvg_Result tvg_engine_init(Tvg_Engine engine_method, unsigned threads)
|
||||
TVG_API Tvg_Result tvg_engine_init(unsigned threads)
|
||||
{
|
||||
return (Tvg_Result) Initializer::init(threads, CanvasEngine(engine_method));
|
||||
return (Tvg_Result) Initializer::init(threads);
|
||||
}
|
||||
|
||||
|
||||
TVG_API Tvg_Result tvg_engine_term(Tvg_Engine engine_method)
|
||||
TVG_API Tvg_Result tvg_engine_term()
|
||||
{
|
||||
return (Tvg_Result) Initializer::term(CanvasEngine(engine_method));
|
||||
return (Tvg_Result) Initializer::term();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,17 +34,7 @@
|
|||
|
||||
#define NOISE_LEVEL 0.5f
|
||||
|
||||
static atomic<int32_t> initEngineCnt{};
|
||||
static atomic<int32_t> rendererCnt{};
|
||||
|
||||
|
||||
static void _termEngine()
|
||||
{
|
||||
if (rendererCnt > 0) return;
|
||||
|
||||
//TODO: Clean up global resources
|
||||
}
|
||||
|
||||
static atomic<int32_t> rendererCnt{-1};
|
||||
|
||||
void GlRenderer::clearDisposes()
|
||||
{
|
||||
|
@ -88,6 +78,7 @@ void GlRenderer::currentContext()
|
|||
|
||||
GlRenderer::GlRenderer()
|
||||
{
|
||||
++rendererCnt;
|
||||
}
|
||||
|
||||
|
||||
|
@ -99,7 +90,7 @@ GlRenderer::~GlRenderer()
|
|||
|
||||
ARRAY_FOREACH(p, mPrograms) delete(*p);
|
||||
|
||||
if (rendererCnt == 0 && initEngineCnt == 0) _termEngine();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1520,45 +1511,33 @@ bool GlRenderer::postUpdate()
|
|||
}
|
||||
|
||||
|
||||
bool GlRenderer::init(uint32_t threads)
|
||||
{
|
||||
if ((initEngineCnt++) > 0) return true;
|
||||
|
||||
//TODO: runtime linking?
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int32_t GlRenderer::init()
|
||||
{
|
||||
return initEngineCnt;
|
||||
}
|
||||
|
||||
|
||||
bool GlRenderer::term()
|
||||
{
|
||||
if ((--initEngineCnt) > 0) return true;
|
||||
if (rendererCnt > 0) return false;
|
||||
|
||||
initEngineCnt = 0;
|
||||
//TODO: clean up global resources
|
||||
|
||||
_termEngine();
|
||||
rendererCnt = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
GlRenderer* GlRenderer::gen()
|
||||
GlRenderer* GlRenderer::gen(TVG_UNUSED uint32_t threads)
|
||||
{
|
||||
//TODO: GL minimum version check, should be replaced with the runtime linking in GlRenderer::init()
|
||||
GLint vMajor, vMinor;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &vMajor);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &vMinor);
|
||||
if (vMajor < TVG_REQUIRE_GL_MAJOR_VER || (vMajor == TVG_REQUIRE_GL_MAJOR_VER && vMinor < TVG_REQUIRE_GL_MINOR_VER)) {
|
||||
TVGERR("GL_ENGINE", "OpenGL/ES version is not satisfied. Current: v%d.%d, Required: v%d.%d", vMajor, vMinor, TVG_REQUIRE_GL_MAJOR_VER, TVG_REQUIRE_GL_MINOR_VER);
|
||||
return nullptr;
|
||||
//initialize engine
|
||||
if (rendererCnt == -1) {
|
||||
//TODO: GL minimum version check, should be replaced with the runtime linking in GlRenderer::init()
|
||||
GLint vMajor, vMinor;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &vMajor);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &vMinor);
|
||||
if (vMajor < TVG_REQUIRE_GL_MAJOR_VER || (vMajor == TVG_REQUIRE_GL_MAJOR_VER && vMinor < TVG_REQUIRE_GL_MINOR_VER)) {
|
||||
TVGERR("GL_ENGINE", "OpenGL/ES version is not satisfied. Current: v%d.%d, Required: v%d.%d", vMajor, vMinor, TVG_REQUIRE_GL_MAJOR_VER, TVG_REQUIRE_GL_MINOR_VER);
|
||||
return nullptr;
|
||||
}
|
||||
TVGLOG("GL_ENGINE", "OpenGL/ES version = v%d.%d", vMajor, vMinor);
|
||||
rendererCnt = 0;
|
||||
}
|
||||
TVGLOG("GL_ENGINE", "OpenGL/ES version = v%d.%d", vMajor, vMinor);
|
||||
|
||||
return new GlRenderer();
|
||||
return new GlRenderer;
|
||||
}
|
|
@ -99,9 +99,7 @@ public:
|
|||
bool render(RenderCompositor* cmp, const RenderEffect* effect, bool direct) override;
|
||||
void dispose(RenderEffect* effect) override;
|
||||
|
||||
static GlRenderer* gen();
|
||||
static bool init(TVG_UNUSED uint32_t threads);
|
||||
static int32_t init();
|
||||
static GlRenderer* gen(uint32_t threads);
|
||||
static bool term();
|
||||
|
||||
private:
|
||||
|
|
|
@ -184,7 +184,7 @@ bool effectGaussianBlur(SwCompositor* cmp, SwSurface* surface, const RenderEffec
|
|||
auto back = buffer.buf32;
|
||||
auto swapped = false;
|
||||
|
||||
TVGLOG("SW_ENGINE", "GaussianFilter region(%ld, %ld, %ld, %ld) params(%f %d %d), level(%d)", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y, params->sigma, params->direction, params->border, data->level);
|
||||
TVGLOG("SW_ENGINE", "GaussianFilter region(%d, %d, %d, %d) params(%f %d %d), level(%d)", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y, params->sigma, params->direction, params->border, data->level);
|
||||
|
||||
/* It is best to take advantage of the Gaussian blur’s separable property
|
||||
by dividing the process into two passes. horizontal and vertical.
|
||||
|
@ -363,7 +363,7 @@ bool effectDropShadow(SwCompositor* cmp, SwSurface* surface[2], const RenderEffe
|
|||
|
||||
auto opacity = direct ? MULTIPLY(params->color[3], cmp->opacity) : params->color[3];
|
||||
|
||||
TVGLOG("SW_ENGINE", "DropShadow region(%ld, %ld, %ld, %ld) params(%f %f %f), level(%d)", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y, params->angle, params->distance, params->sigma, data->level);
|
||||
TVGLOG("SW_ENGINE", "DropShadow region(%d, %d, %d, %d) params(%f %f %f), level(%d)", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y, params->angle, params->distance, params->sigma, data->level);
|
||||
|
||||
//saving the original image in order to overlay it into the filtered image.
|
||||
_dropShadowFilter(back, front, stride, w, h, bbox, data->kernel[0], color, false);
|
||||
|
@ -433,7 +433,7 @@ bool effectFill(SwCompositor* cmp, const RenderEffectFill* params, bool direct)
|
|||
auto h = size_t(bbox.max.y - bbox.min.y);
|
||||
auto color = cmp->recoverSfc->join(params->color[0], params->color[1], params->color[2], 255);
|
||||
|
||||
TVGLOG("SW_ENGINE", "Fill region(%ld, %ld, %ld, %ld), param(%d %d %d %d)", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y, params->color[0], params->color[1], params->color[2], params->color[3]);
|
||||
TVGLOG("SW_ENGINE", "Fill region(%d, %d, %d, %d), param(%d %d %d %d)", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y, params->color[0], params->color[1], params->color[2], params->color[3]);
|
||||
|
||||
if (direct) {
|
||||
auto dbuffer = cmp->recoverSfc->buf32 + (bbox.min.y * cmp->recoverSfc->stride + bbox.min.x);
|
||||
|
@ -484,7 +484,7 @@ bool effectTint(SwCompositor* cmp, const RenderEffectTint* params, bool direct)
|
|||
auto opacity = cmp->opacity;
|
||||
auto luma = cmp->recoverSfc->alphas[2]; //luma function
|
||||
|
||||
TVGLOG("SW_ENGINE", "Tint region(%ld, %ld, %ld, %ld), param(%d %d %d, %d %d %d, %d)", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y, params->black[0], params->black[1], params->black[2], params->white[0], params->white[1], params->white[2], params->intensity);
|
||||
TVGLOG("SW_ENGINE", "Tint region(%d, %d, %d, %d), param(%d %d %d, %d %d %d, %d)", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y, params->black[0], params->black[1], params->black[2], params->white[0], params->white[1], params->white[2], params->intensity);
|
||||
|
||||
/* Tint Formula: (1 - L) * Black + L * White, where the L is Luminance. */
|
||||
|
||||
|
@ -558,7 +558,7 @@ bool effectTritone(SwCompositor* cmp, const RenderEffectTritone* params, bool di
|
|||
auto opacity = cmp->opacity;
|
||||
auto luma = cmp->recoverSfc->alphas[2]; //luma function
|
||||
|
||||
TVGLOG("SW_ENGINE", "Tritone region(%ld, %ld, %ld, %ld), param(%d %d %d, %d %d %d, %d %d %d)", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y, params->shadow[0], params->shadow[1], params->shadow[2], params->midtone[0], params->midtone[1], params->midtone[2], params->highlight[0], params->highlight[1], params->highlight[2]);
|
||||
TVGLOG("SW_ENGINE", "Tritone region(%d, %d, %d, %d), param(%d %d %d, %d %d %d, %d %d %d)", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y, params->shadow[0], params->shadow[1], params->shadow[2], params->midtone[0], params->midtone[1], params->midtone[2], params->highlight[0], params->highlight[1], params->highlight[2]);
|
||||
|
||||
if (direct) {
|
||||
auto dbuffer = cmp->recoverSfc->buf32 + (bbox.min.y * cmp->recoverSfc->stride + bbox.min.x);
|
||||
|
|
|
@ -362,7 +362,7 @@ static bool _rasterMaskedRect(SwSurface* surface, const SwBBox& region, const Re
|
|||
//8bit masking channels composition
|
||||
if (surface->channelSize != sizeof(uint8_t)) return false;
|
||||
|
||||
TVGLOG("SW_ENGINE", "Masked(%d) Rect [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y);
|
||||
TVGLOG("SW_ENGINE", "Masked(%d) Rect [Region: %d %d %d %d]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y);
|
||||
|
||||
auto maskOp = _getMaskOp(surface->compositor->method);
|
||||
if (_direct(surface->compositor->method)) return _rasterDirectMaskedRect(surface, region, maskOp, c.a);
|
||||
|
@ -379,7 +379,7 @@ static bool _rasterMattedRect(SwSurface* surface, const SwBBox& region, const Re
|
|||
auto cbuffer = surface->compositor->image.buf8 + ((region.min.y * surface->compositor->image.stride + region.min.x) * csize); //compositor buffer
|
||||
auto alpha = surface->alpha(surface->compositor->method);
|
||||
|
||||
TVGLOG("SW_ENGINE", "Matted(%d) Rect [Region: %lu %lu %u %u]", (int)surface->compositor->method, region.min.x, region.min.y, w, h);
|
||||
TVGLOG("SW_ENGINE", "Matted(%d) Rect [Region: %d %d %u %u]", (int)surface->compositor->method, region.min.x, region.min.y, w, h);
|
||||
|
||||
//32bits channels
|
||||
if (surface->channelSize == sizeof(uint32_t)) {
|
||||
|
@ -917,7 +917,7 @@ static bool _rasterScaledMattedImage(SwSurface* surface, const SwImage* image, c
|
|||
auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize;
|
||||
auto alpha = surface->alpha(surface->compositor->method);
|
||||
|
||||
TVGLOG("SW_ENGINE", "Scaled Matted(%d) Image [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y);
|
||||
TVGLOG("SW_ENGINE", "Scaled Matted(%d) Image [Region: %d %d %d %d]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y);
|
||||
|
||||
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
|
||||
auto sampleSize = _sampleSize(image->scale);
|
||||
|
@ -1039,7 +1039,7 @@ static bool _rasterDirectMattedImage(SwSurface* surface, const SwImage* image, c
|
|||
auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
|
||||
auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; //compositor buffer
|
||||
|
||||
TVGLOG("SW_ENGINE", "Direct Matted(%d) Image [Region: %lu %lu %u %u]", (int)surface->compositor->method, region.min.x, region.min.y, w, h);
|
||||
TVGLOG("SW_ENGINE", "Direct Matted(%d) Image [Region: %d %d %u %u]", (int)surface->compositor->method, region.min.x, region.min.y, w, h);
|
||||
|
||||
//32 bits
|
||||
if (surface->channelSize == sizeof(uint32_t)) {
|
||||
|
@ -1269,7 +1269,7 @@ static bool _rasterGradientMaskedRect(SwSurface* surface, const SwBBox& region,
|
|||
{
|
||||
auto method = surface->compositor->method;
|
||||
|
||||
TVGLOG("SW_ENGINE", "Masked(%d) Gradient [Region: %lu %lu %lu %lu]", (int)method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y);
|
||||
TVGLOG("SW_ENGINE", "Masked(%d) Gradient [Region: %d %d %d %d]", (int)method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y);
|
||||
|
||||
auto maskOp = _getMaskOp(method);
|
||||
|
||||
|
@ -1290,7 +1290,7 @@ static bool _rasterGradientMattedRect(SwSurface* surface, const SwBBox& region,
|
|||
auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize;
|
||||
auto alpha = surface->alpha(surface->compositor->method);
|
||||
|
||||
TVGLOG("SW_ENGINE", "Matted(%d) Gradient [Region: %lu %lu %u %u]", (int)surface->compositor->method, region.min.x, region.min.y, w, h);
|
||||
TVGLOG("SW_ENGINE", "Matted(%d) Gradient [Region: %d %d %u %u]", (int)surface->compositor->method, region.min.x, region.min.y, w, h);
|
||||
|
||||
for (uint32_t y = 0; y < h; ++y) {
|
||||
fillMethod()(fill, buffer, region.min.y + y, region.min.x, w, cbuffer, alpha, csize, 255);
|
||||
|
|
|
@ -32,8 +32,7 @@
|
|||
/************************************************************************/
|
||||
/* Internal Class Implementation */
|
||||
/************************************************************************/
|
||||
static atomic<int32_t> initEngineCnt{};
|
||||
static atomic<int32_t> rendererCnt{};
|
||||
static atomic<int32_t> rendererCnt{-1};
|
||||
static SwMpool* globalMpool = nullptr;
|
||||
static uint32_t threadsCnt = 0;
|
||||
|
||||
|
@ -242,15 +241,6 @@ struct SwImageTask : SwTask
|
|||
};
|
||||
|
||||
|
||||
static void _termEngine()
|
||||
{
|
||||
if (rendererCnt > 0) return;
|
||||
|
||||
mpoolTerm(globalMpool);
|
||||
globalMpool = nullptr;
|
||||
}
|
||||
|
||||
|
||||
static void _renderFill(SwShapeTask* task, SwSurface* surface, uint8_t opacity)
|
||||
{
|
||||
if (auto fill = task->rshape->fill) {
|
||||
|
@ -280,6 +270,21 @@ static void _renderStroke(SwShapeTask* task, SwSurface* surface, uint8_t opacity
|
|||
/* External Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
SwRenderer::SwRenderer()
|
||||
{
|
||||
if (TaskScheduler::onthread()) {
|
||||
TVGLOG("SW_RENDERER", "Running on a non-dominant thread!, Renderer(%p)", this);
|
||||
mpool = mpoolInit(threadsCnt);
|
||||
sharedMpool = false;
|
||||
} else {
|
||||
mpool = globalMpool;
|
||||
sharedMpool = true;
|
||||
}
|
||||
|
||||
++rendererCnt;
|
||||
}
|
||||
|
||||
|
||||
SwRenderer::~SwRenderer()
|
||||
{
|
||||
clearCompositors();
|
||||
|
@ -289,8 +294,6 @@ SwRenderer::~SwRenderer()
|
|||
if (!sharedMpool) mpoolTerm(mpool);
|
||||
|
||||
--rendererCnt;
|
||||
|
||||
if (rendererCnt == 0 && initEngineCnt == 0) _termEngine();
|
||||
}
|
||||
|
||||
|
||||
|
@ -777,59 +780,30 @@ RenderData SwRenderer::prepare(const RenderShape& rshape, RenderData data, const
|
|||
}
|
||||
|
||||
|
||||
SwRenderer::SwRenderer()
|
||||
{
|
||||
if (TaskScheduler::onthread()) {
|
||||
TVGLOG("SW_RENDERER", "Running on a non-dominant thread!, Renderer(%p)", this);
|
||||
mpool = mpoolInit(threadsCnt);
|
||||
sharedMpool = false;
|
||||
} else {
|
||||
mpool = globalMpool;
|
||||
sharedMpool = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SwRenderer::init(uint32_t threads)
|
||||
{
|
||||
if ((initEngineCnt++) > 0) return true;
|
||||
|
||||
threadsCnt = threads;
|
||||
|
||||
//Share the memory pool among the renderer
|
||||
globalMpool = mpoolInit(threads);
|
||||
if (!globalMpool) {
|
||||
--initEngineCnt;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int32_t SwRenderer::init()
|
||||
{
|
||||
#ifdef THORVG_SW_OPENMP_SUPPORT
|
||||
omp_set_num_threads(TaskScheduler::threads());
|
||||
#endif
|
||||
|
||||
return initEngineCnt;
|
||||
}
|
||||
|
||||
|
||||
bool SwRenderer::term()
|
||||
{
|
||||
if ((--initEngineCnt) > 0) return true;
|
||||
if (rendererCnt > 0) return false;
|
||||
|
||||
initEngineCnt = 0;
|
||||
|
||||
_termEngine();
|
||||
mpoolTerm(globalMpool);
|
||||
globalMpool = nullptr;
|
||||
rendererCnt = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SwRenderer* SwRenderer::gen()
|
||||
|
||||
SwRenderer* SwRenderer::gen(uint32_t threads)
|
||||
{
|
||||
++rendererCnt;
|
||||
return new SwRenderer();
|
||||
//initialize engine
|
||||
if (rendererCnt == -1) {
|
||||
#ifdef THORVG_SW_OPENMP_SUPPORT
|
||||
omp_set_num_threads(threads);
|
||||
#endif
|
||||
//Share the memory pool among the renderer
|
||||
globalMpool = mpoolInit(threads);
|
||||
threadsCnt = threads;
|
||||
rendererCnt = 0;
|
||||
}
|
||||
|
||||
return new SwRenderer;
|
||||
}
|
||||
|
|
|
@ -66,9 +66,7 @@ public:
|
|||
bool render(RenderCompositor* cmp, const RenderEffect* effect, bool direct) override;
|
||||
void dispose(RenderEffect* effect) override;
|
||||
|
||||
static SwRenderer* gen();
|
||||
static bool init(uint32_t threads);
|
||||
static int32_t init();
|
||||
static SwRenderer* gen(uint32_t threads);
|
||||
static bool term();
|
||||
|
||||
private:
|
||||
|
|
|
@ -116,6 +116,8 @@ namespace tvg {
|
|||
{
|
||||
std::free(ptr);
|
||||
}
|
||||
|
||||
extern int engineInit;
|
||||
}
|
||||
|
||||
#endif //_TVG_COMMON_H_
|
||||
|
|
|
@ -21,23 +21,19 @@
|
|||
*/
|
||||
|
||||
#include "tvgCanvas.h"
|
||||
#include "tvgTaskScheduler.h"
|
||||
|
||||
#ifdef THORVG_GL_RASTER_SUPPORT
|
||||
#include "tvgGlRenderer.h"
|
||||
#endif
|
||||
|
||||
GlCanvas::GlCanvas()
|
||||
{
|
||||
#ifdef THORVG_GL_RASTER_SUPPORT
|
||||
pImpl->renderer = GlRenderer::gen();
|
||||
pImpl->renderer->ref();
|
||||
#endif
|
||||
}
|
||||
|
||||
GlCanvas::GlCanvas() = default;
|
||||
|
||||
GlCanvas::~GlCanvas()
|
||||
{
|
||||
//TODO:
|
||||
#ifdef THORVG_GL_RASTER_SUPPORT
|
||||
GlRenderer::term();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,8 +66,14 @@ Result GlCanvas::target(void* context, int32_t id, uint32_t w, uint32_t h, Color
|
|||
GlCanvas* GlCanvas::gen() noexcept
|
||||
{
|
||||
#ifdef THORVG_GL_RASTER_SUPPORT
|
||||
if (GlRenderer::init() <= 0) return nullptr;
|
||||
return new GlCanvas;
|
||||
if (engineInit > 0) {
|
||||
auto renderer = GlRenderer::gen(TaskScheduler::threads());
|
||||
if (!renderer) return nullptr;
|
||||
renderer->ref();
|
||||
auto ret = new GlCanvas;
|
||||
ret->pImpl->renderer = renderer;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -41,14 +41,12 @@
|
|||
/* Internal Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
static int _initCnt = 0;
|
||||
namespace tvg {
|
||||
int engineInit = 0;
|
||||
}
|
||||
|
||||
static uint16_t _version = 0;
|
||||
|
||||
//enum class operation helper
|
||||
static constexpr bool operator &(CanvasEngine a, CanvasEngine b)
|
||||
{
|
||||
return int(a) & int(b);
|
||||
}
|
||||
|
||||
static bool _buildVersionInfo(uint32_t* major, uint32_t* minor, uint32_t* micro)
|
||||
{
|
||||
|
@ -82,34 +80,9 @@ static bool _buildVersionInfo(uint32_t* major, uint32_t* minor, uint32_t* micro)
|
|||
/* External Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
Result Initializer::init(uint32_t threads, CanvasEngine engine) noexcept
|
||||
Result Initializer::init(uint32_t threads) noexcept
|
||||
{
|
||||
auto nonSupport = true;
|
||||
|
||||
if (engine == CanvasEngine::All || engine & CanvasEngine::Sw) {
|
||||
#ifdef THORVG_SW_RASTER_SUPPORT
|
||||
if (!SwRenderer::init(threads)) return Result::FailedAllocation;
|
||||
nonSupport = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (engine == CanvasEngine::All || engine & CanvasEngine::Gl) {
|
||||
#ifdef THORVG_GL_RASTER_SUPPORT
|
||||
if (!GlRenderer::init(threads)) return Result::FailedAllocation;
|
||||
nonSupport = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (engine == CanvasEngine::All || engine & CanvasEngine::Wg) {
|
||||
#ifdef THORVG_WG_RASTER_SUPPORT
|
||||
if (!WgRenderer::init(threads)) return Result::FailedAllocation;
|
||||
nonSupport = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (nonSupport) return Result::NonSupport;
|
||||
|
||||
if (_initCnt++ > 0) return Result::Success;
|
||||
if (engineInit++ > 0) return Result::Success;
|
||||
|
||||
if (!_buildVersionInfo(nullptr, nullptr, nullptr)) return Result::Unknown;
|
||||
|
||||
|
@ -121,36 +94,23 @@ Result Initializer::init(uint32_t threads, CanvasEngine engine) noexcept
|
|||
}
|
||||
|
||||
|
||||
Result Initializer::term(CanvasEngine engine) noexcept
|
||||
Result Initializer::term() noexcept
|
||||
{
|
||||
if (_initCnt == 0) return Result::InsufficientCondition;
|
||||
if (engineInit == 0) return Result::InsufficientCondition;
|
||||
|
||||
auto nonSupport = true;
|
||||
if (--engineInit > 0) return Result::Success;
|
||||
|
||||
if (engine == CanvasEngine::All || engine & CanvasEngine::Sw) {
|
||||
#ifdef THORVG_SW_RASTER_SUPPORT
|
||||
if (!SwRenderer::term()) return Result::InsufficientCondition;
|
||||
nonSupport = false;
|
||||
#endif
|
||||
}
|
||||
#ifdef THORVG_SW_RASTER_SUPPORT
|
||||
if (!SwRenderer::term()) return Result::InsufficientCondition;
|
||||
#endif
|
||||
|
||||
if (engine == CanvasEngine::All || engine & CanvasEngine::Gl) {
|
||||
#ifdef THORVG_GL_RASTER_SUPPORT
|
||||
if (!GlRenderer::term()) return Result::InsufficientCondition;
|
||||
nonSupport = false;
|
||||
#endif
|
||||
}
|
||||
#ifdef THORVG_GL_RASTER_SUPPORT
|
||||
if (!GlRenderer::term()) return Result::InsufficientCondition;
|
||||
#endif
|
||||
|
||||
if (engine == CanvasEngine::All || engine & CanvasEngine::Wg) {
|
||||
#ifdef THORVG_WG_RASTER_SUPPORT
|
||||
if (!WgRenderer::term()) return Result::InsufficientCondition;
|
||||
nonSupport = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (nonSupport) return Result::NonSupport;
|
||||
|
||||
if (--_initCnt > 0) return Result::Success;
|
||||
#ifdef THORVG_WG_RASTER_SUPPORT
|
||||
if (!WgRenderer::term()) return Result::InsufficientCondition;
|
||||
#endif
|
||||
|
||||
TaskScheduler::term();
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*/
|
||||
|
||||
#include "tvgCanvas.h"
|
||||
#include "tvgTaskScheduler.h"
|
||||
#include "tvgLoadModule.h"
|
||||
|
||||
#ifdef THORVG_SW_RASTER_SUPPORT
|
||||
|
@ -28,18 +29,13 @@
|
|||
#endif
|
||||
|
||||
|
||||
SwCanvas::SwCanvas()
|
||||
{
|
||||
#ifdef THORVG_SW_RASTER_SUPPORT
|
||||
pImpl->renderer = SwRenderer::gen();
|
||||
pImpl->renderer->ref();
|
||||
#endif
|
||||
}
|
||||
|
||||
SwCanvas::SwCanvas() = default;
|
||||
|
||||
SwCanvas::~SwCanvas()
|
||||
{
|
||||
//TODO:
|
||||
#ifdef THORVG_SW_RASTER_SUPPORT
|
||||
SwRenderer::term();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -76,8 +72,13 @@ Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
|
|||
SwCanvas* SwCanvas::gen() noexcept
|
||||
{
|
||||
#ifdef THORVG_SW_RASTER_SUPPORT
|
||||
if (SwRenderer::init() <= 0) return nullptr;
|
||||
return new SwCanvas;
|
||||
if (engineInit > 0) {
|
||||
auto renderer = SwRenderer::gen(TaskScheduler::threads());
|
||||
renderer->ref();
|
||||
auto ret = new SwCanvas;
|
||||
ret->pImpl->renderer = renderer;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -21,26 +21,22 @@
|
|||
*/
|
||||
|
||||
#include "tvgCanvas.h"
|
||||
#include "tvgTaskScheduler.h"
|
||||
|
||||
#ifdef THORVG_WG_RASTER_SUPPORT
|
||||
#include "tvgWgRenderer.h"
|
||||
#endif
|
||||
|
||||
|
||||
WgCanvas::WgCanvas()
|
||||
{
|
||||
#ifdef THORVG_WG_RASTER_SUPPORT
|
||||
pImpl->renderer = WgRenderer::gen();
|
||||
pImpl->renderer->ref();
|
||||
#endif
|
||||
}
|
||||
|
||||
WgCanvas::WgCanvas() = default;
|
||||
|
||||
WgCanvas::~WgCanvas()
|
||||
{
|
||||
#ifdef THORVG_WG_RASTER_SUPPORT
|
||||
auto renderer = static_cast<WgRenderer*>(pImpl->renderer);
|
||||
renderer->target(nullptr, nullptr, nullptr, 0, 0);
|
||||
|
||||
WgRenderer::term();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -74,8 +70,13 @@ Result WgCanvas::target(void* device, void* instance, void* target, uint32_t w,
|
|||
WgCanvas* WgCanvas::gen() noexcept
|
||||
{
|
||||
#ifdef THORVG_WG_RASTER_SUPPORT
|
||||
if (WgRenderer::init() <= 0) return nullptr;
|
||||
return new WgCanvas;
|
||||
if (engineInit > 0) {
|
||||
auto renderer = WgRenderer::gen(TaskScheduler::threads());
|
||||
renderer->ref();
|
||||
auto ret = new WgCanvas;
|
||||
ret->pImpl->renderer = renderer;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -29,16 +29,7 @@
|
|||
/* Internal Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
static atomic<int32_t> initEngineCnt{};
|
||||
static atomic<int32_t> rendererCnt{};
|
||||
|
||||
|
||||
static void _termEngine()
|
||||
{
|
||||
if (rendererCnt > 0) return;
|
||||
|
||||
//TODO:
|
||||
}
|
||||
static atomic<int32_t> rendererCnt{-1};
|
||||
|
||||
|
||||
void WgRenderer::release()
|
||||
|
@ -426,6 +417,8 @@ WgRenderer::WgRenderer()
|
|||
} else {
|
||||
mBufferPool.pool = WgGeometryBufferPool::instance();
|
||||
}
|
||||
|
||||
++rendererCnt;
|
||||
}
|
||||
|
||||
|
||||
|
@ -436,8 +429,6 @@ WgRenderer::~WgRenderer()
|
|||
if (mBufferPool.individual) delete(mBufferPool.pool);
|
||||
|
||||
--rendererCnt;
|
||||
|
||||
if (rendererCnt == 0 && initEngineCnt == 0) _termEngine();
|
||||
}
|
||||
|
||||
|
||||
|
@ -648,36 +639,24 @@ bool WgRenderer::postUpdate()
|
|||
}
|
||||
|
||||
|
||||
bool WgRenderer::init(TVG_UNUSED uint32_t threads)
|
||||
{
|
||||
if ((initEngineCnt++) > 0) return true;
|
||||
|
||||
//TODO: global engine init
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int32_t WgRenderer::init()
|
||||
{
|
||||
return initEngineCnt;
|
||||
}
|
||||
|
||||
|
||||
bool WgRenderer::term()
|
||||
{
|
||||
if ((--initEngineCnt) > 0) return true;
|
||||
if (rendererCnt > 0) return false;
|
||||
|
||||
initEngineCnt = 0;
|
||||
//TODO: clean up global resources
|
||||
|
||||
_termEngine();
|
||||
rendererCnt = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
WgRenderer* WgRenderer::gen()
|
||||
WgRenderer* WgRenderer::gen(TVG_UNUSED uint32_t threads)
|
||||
{
|
||||
++rendererCnt;
|
||||
return new WgRenderer();
|
||||
//initialize engine
|
||||
if (rendererCnt == -1) {
|
||||
//TODO:
|
||||
}
|
||||
|
||||
return new WgRenderer;
|
||||
}
|
|
@ -58,9 +58,7 @@ public:
|
|||
bool render(RenderCompositor* cmp, const RenderEffect* effect, bool direct) override;
|
||||
void dispose(RenderEffect* effect) override;
|
||||
|
||||
static WgRenderer* gen();
|
||||
static bool init(uint32_t threads);
|
||||
static int32_t init();
|
||||
static WgRenderer* gen(uint32_t threads);
|
||||
static bool term();
|
||||
|
||||
private:
|
||||
|
|
|
@ -41,46 +41,46 @@ TEST_CASE("Accessor Creation", "[tvgAccessor]")
|
|||
TEST_CASE("Set", "[tvgAccessor]")
|
||||
{
|
||||
REQUIRE(Initializer::init(0) == Result::Success);
|
||||
|
||||
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
|
||||
REQUIRE(canvas);
|
||||
|
||||
uint32_t buffer[100*100];
|
||||
REQUIRE(canvas->target(buffer, 100, 100, 100, ColorSpace::ABGR8888) == Result::Success);
|
||||
|
||||
auto picture = unique_ptr<Picture>(Picture::gen());
|
||||
REQUIRE(picture);
|
||||
REQUIRE(picture->load(TEST_DIR"/logo.svg") == Result::Success);
|
||||
|
||||
auto accessor = unique_ptr<Accessor>(Accessor::gen());
|
||||
REQUIRE(accessor);
|
||||
|
||||
//Case 1
|
||||
REQUIRE(accessor->set(picture.get(), nullptr, nullptr) == Result::InvalidArguments);
|
||||
|
||||
//Case 2
|
||||
Shape* ret = nullptr;
|
||||
|
||||
auto f = [](const tvg::Paint* paint, void* data) -> bool
|
||||
{
|
||||
if (paint->type() == Type::Shape) {
|
||||
auto shape = (tvg::Shape*) paint;
|
||||
uint8_t r, g, b;
|
||||
shape->fill(&r, &g, &b);
|
||||
if (r == 37 && g == 47 && b == 53) {
|
||||
shape->fill(0, 0, 255);
|
||||
shape->id = Accessor::id("TestAccessor");
|
||||
*static_cast<Shape**>(data) = shape;
|
||||
return false;
|
||||
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
|
||||
REQUIRE(canvas);
|
||||
|
||||
uint32_t buffer[100*100];
|
||||
REQUIRE(canvas->target(buffer, 100, 100, 100, ColorSpace::ABGR8888) == Result::Success);
|
||||
|
||||
auto picture = unique_ptr<Picture>(Picture::gen());
|
||||
REQUIRE(picture);
|
||||
REQUIRE(picture->load(TEST_DIR"/logo.svg") == Result::Success);
|
||||
|
||||
auto accessor = unique_ptr<Accessor>(Accessor::gen());
|
||||
REQUIRE(accessor);
|
||||
|
||||
//Case 1
|
||||
REQUIRE(accessor->set(picture.get(), nullptr, nullptr) == Result::InvalidArguments);
|
||||
|
||||
//Case 2
|
||||
Shape* ret = nullptr;
|
||||
|
||||
auto f = [](const tvg::Paint* paint, void* data) -> bool
|
||||
{
|
||||
if (paint->type() == Type::Shape) {
|
||||
auto shape = (tvg::Shape*) paint;
|
||||
uint8_t r, g, b;
|
||||
shape->fill(&r, &g, &b);
|
||||
if (r == 37 && g == 47 && b == 53) {
|
||||
shape->fill(0, 0, 255);
|
||||
shape->id = Accessor::id("TestAccessor");
|
||||
*static_cast<Shape**>(data) = shape;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
REQUIRE(accessor->set(picture.get(), f, &ret) == Result::Success);
|
||||
|
||||
REQUIRE((ret && ret->id == Accessor::id("TestAccessor")));
|
||||
REQUIRE(accessor->set(picture.get(), f, &ret) == Result::Success);
|
||||
|
||||
REQUIRE((ret && ret->id == Accessor::id("TestAccessor")));
|
||||
}
|
||||
REQUIRE(Initializer::term() == Result::Success);
|
||||
}
|
||||
|
||||
|
|
|
@ -58,9 +58,4 @@ TEST_CASE("Version", "[tvgInitializer]")
|
|||
TEST_CASE("Negative termination", "[tvgInitializer]")
|
||||
{
|
||||
REQUIRE(Initializer::term() == Result::InsufficientCondition);
|
||||
}
|
||||
|
||||
TEST_CASE("Invalid engine", "[tvgInitializer]")
|
||||
{
|
||||
REQUIRE(Initializer::init(0, CanvasEngine(64)) == Result::NonSupport);
|
||||
}
|
||||
}
|
|
@ -71,30 +71,30 @@ TEST_CASE("Load RAW Data", "[tvgPicture]")
|
|||
TEST_CASE("Load RAW file and render", "[tvgPicture]")
|
||||
{
|
||||
REQUIRE(Initializer::init(0) == Result::Success);
|
||||
{
|
||||
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
|
||||
REQUIRE(canvas);
|
||||
|
||||
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
|
||||
REQUIRE(canvas);
|
||||
uint32_t buffer[100*100];
|
||||
REQUIRE(canvas->target(buffer, 100, 100, 100, ColorSpace::ABGR8888) == Result::Success);
|
||||
|
||||
uint32_t buffer[100*100];
|
||||
REQUIRE(canvas->target(buffer, 100, 100, 100, ColorSpace::ABGR8888) == Result::Success);
|
||||
ifstream file(TEST_DIR"/rawimage_200x300.raw");
|
||||
if (!file.is_open()) return;
|
||||
auto data = (uint32_t*)malloc(sizeof(uint32_t) * (200*300));
|
||||
file.read(reinterpret_cast<char *>(data), sizeof (uint32_t) * 200 * 300);
|
||||
file.close();
|
||||
|
||||
ifstream file(TEST_DIR"/rawimage_200x300.raw");
|
||||
if (!file.is_open()) return;
|
||||
auto data = (uint32_t*)malloc(sizeof(uint32_t) * (200*300));
|
||||
file.read(reinterpret_cast<char *>(data), sizeof (uint32_t) * 200 * 300);
|
||||
file.close();
|
||||
auto picture = Picture::gen();
|
||||
REQUIRE(picture);
|
||||
|
||||
auto picture = Picture::gen();
|
||||
REQUIRE(picture);
|
||||
REQUIRE(picture->load(data, 200, 300, ColorSpace::ARGB8888, false) == Result::Success);
|
||||
REQUIRE(picture->size(100, 150) == Result::Success);
|
||||
|
||||
REQUIRE(picture->load(data, 200, 300, ColorSpace::ARGB8888, false) == Result::Success);
|
||||
REQUIRE(picture->size(100, 150) == Result::Success);
|
||||
|
||||
REQUIRE(canvas->push(picture) == Result::Success);
|
||||
REQUIRE(canvas->push(picture) == Result::Success);
|
||||
|
||||
free(data);
|
||||
}
|
||||
REQUIRE(Initializer::term() == Result::Success);
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
TEST_CASE("Picture Size", "[tvgPicture]")
|
||||
|
@ -203,28 +203,28 @@ TEST_CASE("Load SVG Data", "[tvgPicture]")
|
|||
TEST_CASE("Load SVG file and render", "[tvgPicture]")
|
||||
{
|
||||
REQUIRE(Initializer::init(0) == Result::Success);
|
||||
{
|
||||
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
|
||||
REQUIRE(canvas);
|
||||
|
||||
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
|
||||
REQUIRE(canvas);
|
||||
auto buffer = new uint32_t[1000*1000];
|
||||
if (!buffer) return;
|
||||
|
||||
auto buffer = new uint32_t[1000*1000];
|
||||
if (!buffer) return;
|
||||
REQUIRE(canvas->target(buffer, 1000, 1000, 1000, ColorSpace::ABGR8888) == Result::Success);
|
||||
|
||||
REQUIRE(canvas->target(buffer, 1000, 1000, 1000, ColorSpace::ABGR8888) == Result::Success);
|
||||
auto picture = Picture::gen();
|
||||
REQUIRE(picture);
|
||||
|
||||
auto picture = Picture::gen();
|
||||
REQUIRE(picture);
|
||||
REQUIRE(picture->load(TEST_DIR"/tag.svg") == Result::Success);
|
||||
REQUIRE(picture->size(100, 100) == Result::Success);
|
||||
|
||||
REQUIRE(picture->load(TEST_DIR"/tag.svg") == Result::Success);
|
||||
REQUIRE(picture->size(100, 100) == Result::Success);
|
||||
|
||||
REQUIRE(canvas->push(picture) == Result::Success);
|
||||
REQUIRE(canvas->draw() == Result::Success);
|
||||
REQUIRE(canvas->sync() == Result::Success);
|
||||
REQUIRE(canvas->push(picture) == Result::Success);
|
||||
REQUIRE(canvas->draw() == Result::Success);
|
||||
REQUIRE(canvas->sync() == Result::Success);
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
REQUIRE(Initializer::term() == Result::Success);
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -275,22 +275,22 @@ TEST_CASE("Load PNG file from data", "[tvgPicture]")
|
|||
TEST_CASE("Load PNG file and render", "[tvgPicture]")
|
||||
{
|
||||
REQUIRE(Initializer::init(0) == Result::Success);
|
||||
{
|
||||
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
|
||||
REQUIRE(canvas);
|
||||
|
||||
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
|
||||
REQUIRE(canvas);
|
||||
uint32_t buffer[100*100];
|
||||
REQUIRE(canvas->target(buffer, 100, 100, 100, ColorSpace::ABGR8888) == Result::Success);
|
||||
|
||||
uint32_t buffer[100*100];
|
||||
REQUIRE(canvas->target(buffer, 100, 100, 100, ColorSpace::ABGR8888) == Result::Success);
|
||||
auto picture = Picture::gen();
|
||||
REQUIRE(picture);
|
||||
|
||||
auto picture = Picture::gen();
|
||||
REQUIRE(picture);
|
||||
|
||||
REQUIRE(picture->load(TEST_DIR"/test.png") == Result::Success);
|
||||
REQUIRE(picture->opacity(192) == Result::Success);
|
||||
REQUIRE(picture->scale(5.0) == Result::Success);
|
||||
|
||||
REQUIRE(canvas->push(picture) == Result::Success);
|
||||
REQUIRE(picture->load(TEST_DIR"/test.png") == Result::Success);
|
||||
REQUIRE(picture->opacity(192) == Result::Success);
|
||||
REQUIRE(picture->scale(5.0) == Result::Success);
|
||||
|
||||
REQUIRE(canvas->push(picture) == Result::Success);
|
||||
}
|
||||
REQUIRE(Initializer::term() == Result::Success);
|
||||
}
|
||||
|
||||
|
@ -345,20 +345,21 @@ TEST_CASE("Load JPG file from data", "[tvgPicture]")
|
|||
TEST_CASE("Load JPG file and render", "[tvgPicture]")
|
||||
{
|
||||
REQUIRE(Initializer::init(0) == Result::Success);
|
||||
{
|
||||
|
||||
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
|
||||
REQUIRE(canvas);
|
||||
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
|
||||
REQUIRE(canvas);
|
||||
|
||||
uint32_t buffer[100*100];
|
||||
REQUIRE(canvas->target(buffer, 100, 100, 100, ColorSpace::ABGR8888) == Result::Success);
|
||||
uint32_t buffer[100*100];
|
||||
REQUIRE(canvas->target(buffer, 100, 100, 100, ColorSpace::ABGR8888) == Result::Success);
|
||||
|
||||
auto picture = Picture::gen();
|
||||
REQUIRE(picture);
|
||||
auto picture = Picture::gen();
|
||||
REQUIRE(picture);
|
||||
|
||||
REQUIRE(picture->load(TEST_DIR"/test.jpg") == Result::Success);
|
||||
|
||||
REQUIRE(canvas->push(picture) == Result::Success);
|
||||
REQUIRE(picture->load(TEST_DIR"/test.jpg") == Result::Success);
|
||||
|
||||
REQUIRE(canvas->push(picture) == Result::Success);
|
||||
}
|
||||
REQUIRE(Initializer::term() == Result::Success);
|
||||
}
|
||||
|
||||
|
@ -410,22 +411,22 @@ TEST_CASE("Load WEBP file from data", "[tvgPicture]")
|
|||
TEST_CASE("Load WEBP file and render", "[tvgPicture]")
|
||||
{
|
||||
REQUIRE(Initializer::init(0) == Result::Success);
|
||||
{
|
||||
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
|
||||
REQUIRE(canvas);
|
||||
|
||||
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
|
||||
REQUIRE(canvas);
|
||||
uint32_t buffer[100*100];
|
||||
REQUIRE(canvas->target(buffer, 100, 100, 100, ColorSpace::ABGR8888) == Result::Success);
|
||||
|
||||
uint32_t buffer[100*100];
|
||||
REQUIRE(canvas->target(buffer, 100, 100, 100, ColorSpace::ABGR8888) == Result::Success);
|
||||
auto picture = Picture::gen();
|
||||
REQUIRE(picture);
|
||||
|
||||
auto picture = Picture::gen();
|
||||
REQUIRE(picture);
|
||||
|
||||
REQUIRE(picture->load(TEST_DIR"/test.webp") == Result::Success);
|
||||
REQUIRE(picture->opacity(192) == Result::Success);
|
||||
REQUIRE(picture->scale(5.0) == Result::Success);
|
||||
|
||||
REQUIRE(canvas->push(picture) == Result::Success);
|
||||
REQUIRE(picture->load(TEST_DIR"/test.webp") == Result::Success);
|
||||
REQUIRE(picture->opacity(192) == Result::Success);
|
||||
REQUIRE(picture->scale(5.0) == Result::Success);
|
||||
|
||||
REQUIRE(canvas->push(picture) == Result::Success);
|
||||
}
|
||||
REQUIRE(Initializer::term() == Result::Success);
|
||||
}
|
||||
|
||||
|
|
|
@ -78,27 +78,27 @@ TEST_CASE("Scene Clear", "[tvgScene]")
|
|||
TEST_CASE("Scene Clear And Reuse Shape", "[tvgScene]")
|
||||
{
|
||||
REQUIRE(Initializer::init(0) == Result::Success);
|
||||
{
|
||||
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
|
||||
REQUIRE(canvas);
|
||||
|
||||
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
|
||||
REQUIRE(canvas);
|
||||
auto scene = Scene::gen();
|
||||
REQUIRE(scene);
|
||||
|
||||
auto scene = Scene::gen();
|
||||
REQUIRE(scene);
|
||||
auto shape = Shape::gen();
|
||||
REQUIRE(shape);
|
||||
REQUIRE(shape->ref() == 1);
|
||||
|
||||
auto shape = Shape::gen();
|
||||
REQUIRE(shape);
|
||||
REQUIRE(shape->ref() == 1);
|
||||
REQUIRE(scene->push(shape) == Result::Success);
|
||||
REQUIRE(canvas->push(scene) == Result::Success);
|
||||
REQUIRE(canvas->update() == Result::Success);
|
||||
|
||||
REQUIRE(scene->push(shape) == Result::Success);
|
||||
REQUIRE(canvas->push(scene) == Result::Success);
|
||||
REQUIRE(canvas->update() == Result::Success);
|
||||
|
||||
//No deallocate shape.
|
||||
REQUIRE(scene->remove() == Result::Success);
|
||||
|
||||
//Reuse shape.
|
||||
REQUIRE(scene->push(shape) == Result::Success);
|
||||
REQUIRE(shape->unref() == 1); //The scene still holds 1.
|
||||
//No deallocate shape.
|
||||
REQUIRE(scene->remove() == Result::Success);
|
||||
|
||||
//Reuse shape.
|
||||
REQUIRE(scene->push(shape) == Result::Success);
|
||||
REQUIRE(shape->unref() == 1); //The scene still holds 1.
|
||||
}
|
||||
REQUIRE(Initializer::term() == Result::Success);
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ private:
|
|||
|
||||
bool convert(string& in, string& out)
|
||||
{
|
||||
if (Initializer::init(0, CanvasEngine::Sw) != Result::Success) return false;
|
||||
if (Initializer::init(0) != Result::Success) return false;
|
||||
|
||||
auto animation = Animation::gen();
|
||||
auto picture = animation->picture();
|
||||
|
|
|
@ -172,7 +172,7 @@ private:
|
|||
if (threads > 0) --threads;
|
||||
|
||||
//Initialize ThorVG Engine
|
||||
if (tvg::Initializer::init(threads, tvg::CanvasEngine::Sw) != tvg::Result::Success) {
|
||||
if (tvg::Initializer::init(threads) != tvg::Result::Success) {
|
||||
cout << "Error: Engine is not supported" << endl;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue