diff --git a/examples/Capi.cpp b/examples/Capi.cpp index db1f032a..b2936de6 100644 --- a/examples/Capi.cpp +++ b/examples/Capi.cpp @@ -303,7 +303,6 @@ int main(int argc, char **argv) //create the canvas canvas = tvg_swcanvas_create(); tvg_swcanvas_set_target(canvas, (uint32_t*)surface->pixels, surface->w, surface->pitch / 4, surface->h, TVG_COLORSPACE_ARGB8888); - tvg_swcanvas_set_mempool(canvas, TVG_MEMPOOL_POLICY_DEFAULT); contents(); diff --git a/inc/thorvg.h b/inc/thorvg.h index ad265549..5ae245a6 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -1666,17 +1666,6 @@ class TVG_API SwCanvas final : public Canvas public: ~SwCanvas(); - /** - * @brief Enumeration specifying the methods of Memory Pool behavior policy. - * @since 0.4 - */ - enum MempoolPolicy : uint8_t - { - Default = 0, ///< Default behavior that ThorVG is designed to. - Shareable, ///< Memory Pool is shared among the SwCanvases. - Individual ///< Allocate designated memory pool that is only used by current instance. - }; - /** * @brief Sets the drawing target for the rasterization. * @@ -1699,30 +1688,6 @@ public: */ Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, ColorSpace cs) noexcept; - /** - * @brief Set sw engine memory pool behavior policy. - * - * Basically ThorVG draws a lot of shapes, it allocates/deallocates a few chunk of memory - * while processing rendering. It internally uses one shared memory pool - * which can be reused among the canvases in order to avoid memory overhead. - * - * Thus ThorVG suggests using a memory pool policy to satisfy user demands, - * if it needs to guarantee the thread-safety of the internal data access. - * - * @param[in] policy The method specifying the Memory Pool behavior. The default value is @c MempoolPolicy::Default. - * - * @retval Result::InsufficientCondition If the canvas contains some paints already. - * @retval Result::NonSupport In case the software engine is not supported. - * - * @note When @c policy is set as @c MempoolPolicy::Individual, the current instance of canvas uses its own individual - * memory data, which is not shared with others. This is necessary when the canvas is accessed on a worker-thread. - * - * @warning It's not allowed after pushing any paints. - * - * @since 0.4 - */ - Result mempool(MempoolPolicy policy) noexcept; - /** * @brief Creates a new SwCanvas object. * @return A new SwCanvas object. diff --git a/src/bindings/capi/thorvg_capi.h b/src/bindings/capi/thorvg_capi.h index 792d2b0d..00627639 100644 --- a/src/bindings/capi/thorvg_capi.h +++ b/src/bindings/capi/thorvg_capi.h @@ -419,16 +419,6 @@ TVG_API Tvg_Result tvg_engine_version(uint32_t* major, uint32_t* minor, uint32_t /* SwCanvas API */ /************************************************************************/ -/** - * @brief Enumeration specifying the methods of Memory Pool behavior policy. - */ -typedef enum { - TVG_MEMPOOL_POLICY_DEFAULT = 0, ///< Default behavior that ThorVG is designed to. - TVG_MEMPOOL_POLICY_SHAREABLE, ///< Memory Pool is shared among canvases. - TVG_MEMPOOL_POLICY_INDIVIDUAL ///< Allocate designated memory pool that is used only by the current canvas instance. -} Tvg_Mempool_Policy; - - /*! * @brief Creates a Canvas object. * @@ -462,31 +452,6 @@ TVG_API Tvg_Canvas* tvg_swcanvas_create(void); TVG_API Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Tvg_Colorspace cs); -/*! -* @brief Sets the software engine memory pool behavior policy. -* -* ThorVG draws a lot of shapes, it allocates/deallocates a few chunk of memory -* while processing rendering. It internally uses one shared memory pool -* which can be reused among the canvases in order to avoid memory overhead. -* -* Thus ThorVG suggests using a memory pool policy to satisfy user demands, -* if it needs to guarantee the thread-safety of the internal data access. -* -* @param[in] canvas The Tvg_Canvas object of which the Memory Pool behavior is to be specified. -* @param[in] policy The method specifying the Memory Pool behavior. The default value is @c TVG_MEMPOOL_POLICY_DEFAULT. -* -* @return Tvg_Result enumeration. -* @retval TVG_RESULT_INVALID_ARGUMENTS An invalid canvas pointer passed. -* @retval TVG_RESULT_INSUFFICIENT_CONDITION The canvas contains some paints already. -* @retval TVG_RESULT_NOT_SUPPORTED The software engine is not supported. -* -* @note When @c policy is set as @c TVG_MEMPOOL_POLICY_INDIVIDUAL, the current instance of canvas uses its own individual -* memory data, which is not shared with others. This is necessary when the canvas is accessed on a worker-thread. -* -* @warning It's not allowed after pushing any paints. -*/ -TVG_API Tvg_Result tvg_swcanvas_set_mempool(Tvg_Canvas* canvas, Tvg_Mempool_Policy policy); - /** \} */ // end defgroup ThorVGCapi_SwCanvas diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp index 426e5353..986a472a 100644 --- a/src/bindings/capi/tvgCapi.cpp +++ b/src/bindings/capi/tvgCapi.cpp @@ -88,13 +88,6 @@ TVG_API Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas) } -TVG_API Tvg_Result tvg_swcanvas_set_mempool(Tvg_Canvas* canvas, Tvg_Mempool_Policy policy) -{ - if (!canvas) return TVG_RESULT_INVALID_ARGUMENT; - return (Tvg_Result) reinterpret_cast(canvas)->mempool(static_cast(policy)); -} - - TVG_API Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Tvg_Colorspace cs) { if (!canvas) return TVG_RESULT_INVALID_ARGUMENT; diff --git a/src/renderer/sw_engine/tvgSwRenderer.cpp b/src/renderer/sw_engine/tvgSwRenderer.cpp index faa44524..1ee24db9 100644 --- a/src/renderer/sw_engine/tvgSwRenderer.cpp +++ b/src/renderer/sw_engine/tvgSwRenderer.cpp @@ -522,26 +522,6 @@ bool SwRenderer::beginComposite(RenderCompositor* cmp, MaskMethod method, uint8_ } -bool SwRenderer::mempool(bool shared) -{ - if (shared == sharedMpool) return true; - - if (shared) { - if (!sharedMpool) { - if (!mpoolTerm(mpool)) return false; - mpool = globalMpool; - } - } else { - if (sharedMpool) mpool = mpoolInit(threadsCnt); - } - - sharedMpool = shared; - - if (mpool) return true; - return false; -} - - const RenderSurface* SwRenderer::mainSurface() { return surface; @@ -811,8 +791,15 @@ RenderData SwRenderer::prepare(const RenderShape& rshape, RenderData data, const } -SwRenderer::SwRenderer():mpool(globalMpool) +SwRenderer::SwRenderer() { + if (TaskScheduler::onthread()) { + TVGLOG("SW_RENDERER", "Running on a non-dominant thread!, Renderer(%p)", this); + mpool = mpoolInit(threadsCnt); + } else { + mpool = globalMpool; + sharedMpool = true; + } } diff --git a/src/renderer/sw_engine/tvgSwRenderer.h b/src/renderer/sw_engine/tvgSwRenderer.h index 6768577a..50123fbb 100644 --- a/src/renderer/sw_engine/tvgSwRenderer.h +++ b/src/renderer/sw_engine/tvgSwRenderer.h @@ -55,7 +55,6 @@ public: bool clear() override; bool sync() override; bool target(pixel_t* data, uint32_t stride, uint32_t w, uint32_t h, ColorSpace cs); - bool mempool(bool shared); RenderCompositor* target(const RenderRegion& region, ColorSpace cs, CompositionFlag flags) override; bool beginComposite(RenderCompositor* cmp, MaskMethod method, uint8_t opacity) override; diff --git a/src/renderer/tvgCanvas.cpp b/src/renderer/tvgCanvas.cpp index 8243d667..ebbb188c 100644 --- a/src/renderer/tvgCanvas.cpp +++ b/src/renderer/tvgCanvas.cpp @@ -81,4 +81,4 @@ Result Canvas::viewport(int32_t x, int32_t y, int32_t w, int32_t h) noexcept Result Canvas::sync() noexcept { return pImpl->sync(); -} +} \ No newline at end of file diff --git a/src/renderer/tvgSwCanvas.cpp b/src/renderer/tvgSwCanvas.cpp index a8ccbbb9..027c9e14 100644 --- a/src/renderer/tvgSwCanvas.cpp +++ b/src/renderer/tvgSwCanvas.cpp @@ -43,25 +43,6 @@ SwCanvas::~SwCanvas() } -Result SwCanvas::mempool(MempoolPolicy policy) noexcept -{ -#ifdef THORVG_SW_RASTER_SUPPORT - //We know renderer type, avoid dynamic_cast for performance. - auto renderer = static_cast(pImpl->renderer); - if (!renderer) return Result::MemoryCorruption; - - //It can't change the policy during the running. - if (!pImpl->scene->paints().empty()) return Result::InsufficientCondition; - - if (policy == MempoolPolicy::Individual) renderer->mempool(false); - else renderer->mempool(true); - - return Result::Success; -#endif - return Result::NonSupport; -} - - Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, ColorSpace cs) noexcept { #ifdef THORVG_SW_RASTER_SUPPORT diff --git a/src/renderer/tvgTaskScheduler.cpp b/src/renderer/tvgTaskScheduler.cpp index 917e58b7..31f77bf8 100644 --- a/src/renderer/tvgTaskScheduler.cpp +++ b/src/renderer/tvgTaskScheduler.cpp @@ -20,14 +20,12 @@ * SOFTWARE. */ +#include +#include #include "tvgArray.h" #include "tvgInlist.h" #include "tvgTaskScheduler.h" -#ifdef THORVG_THREAD_SUPPORT - #include - #include -#endif /************************************************************************/ /* Internal Class Implementation */ @@ -36,7 +34,9 @@ namespace tvg { struct TaskSchedulerImpl; -static TaskSchedulerImpl* inst = nullptr; +static TaskSchedulerImpl* _inst = nullptr; +static std::thread::id _tid; //dominant thread id + #ifdef THORVG_THREAD_SUPPORT @@ -189,6 +189,7 @@ struct TaskSchedulerImpl #endif //THORVG_THREAD_SUPPORT + } //namespace /************************************************************************/ @@ -197,27 +198,28 @@ struct TaskSchedulerImpl void TaskScheduler::init(uint32_t threads) { - if (inst) return; - inst = new TaskSchedulerImpl(threads); + if (_inst) return; + _inst = new TaskSchedulerImpl(threads); + _tid = std::this_thread::get_id(); } void TaskScheduler::term() { - delete(inst); - inst = nullptr; + delete(_inst); + _inst = nullptr; } void TaskScheduler::request(Task* task) { - if (inst) inst->request(task); + if (_inst) _inst->request(task); } uint32_t TaskScheduler::threads() { - if (inst) return inst->threadCnt(); + if (_inst) return _inst->threadCnt(); return 0; } @@ -226,4 +228,9 @@ void TaskScheduler::async(bool on) { //toggle async tasking for each thread on/off _async = on; +} + +bool TaskScheduler::onthread() +{ + return _tid != std::this_thread::get_id(); } \ No newline at end of file diff --git a/src/renderer/tvgTaskScheduler.h b/src/renderer/tvgTaskScheduler.h index 86a9f268..6938bd0a 100644 --- a/src/renderer/tvgTaskScheduler.h +++ b/src/renderer/tvgTaskScheduler.h @@ -104,6 +104,7 @@ struct TaskScheduler static void term(); static void request(Task* task); static void async(bool on); + static bool onthread(); //figure out whether on worker thread or not }; } //namespace diff --git a/src/savers/gif/tvgGifSaver.cpp b/src/savers/gif/tvgGifSaver.cpp index a769e83a..a0669562 100644 --- a/src/savers/gif/tvgGifSaver.cpp +++ b/src/savers/gif/tvgGifSaver.cpp @@ -34,9 +34,6 @@ void GifSaver::run(unsigned tid) auto canvas = unique_ptr(SwCanvas::gen()); if (!canvas) return; - //Do not share the memory pool since this canvas could be running on a thread. - canvas->mempool(SwCanvas::Individual); - auto w = static_cast(vsize[0]); auto h = static_cast(vsize[1]);