From 548962f5f8868429b9ebf5ce6fb9005dcb9a606a Mon Sep 17 00:00:00 2001 From: Sergii Liebodkin Date: Mon, 20 Nov 2023 10:59:38 +0900 Subject: [PATCH] apis/engines: Revise the clear() buffer behavior. ThorVG has offered an option to clear the buffer since version 1.0. This is essential when users utilize the canvas target buffer with the main render target. They share the buffer and need to draw contents onto the existing contents. API: Result Canvas::clear(bool free = true) -> Result Canvas::clear(bool paints = true, bool buffer = true) Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas, bool free); -> Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas, bool paints, bool buffer); Issue: https://github.com/thorvg/thorvg/issues/1779 Co-Authored-By: Hermet Park --- inc/thorvg.h | 5 ++-- src/bindings/capi/thorvg_capi.h | 7 +++-- src/bindings/capi/tvgCapi.cpp | 4 +-- src/examples/Capi.cpp | 1 + src/renderer/gl_engine/tvgGlRenderTask.cpp | 9 +++---- src/renderer/gl_engine/tvgGlRenderTask.h | 2 ++ src/renderer/gl_engine/tvgGlRenderer.cpp | 7 ++--- src/renderer/gl_engine/tvgGlRenderer.h | 5 +++- src/renderer/tvgCanvas.cpp | 4 +-- src/renderer/tvgCanvas.h | 29 +++++++++++---------- src/renderer/wg_engine/tvgWgRenderer.cpp | 12 +++++++-- src/renderer/wg_engine/tvgWgRenderer.h | 2 ++ test/capi/capiSwCanvas.cpp | 6 ++--- test/images/tag.tvg | Bin 3464 -> 3466 bytes test/testSwCanvasBase.cpp | 2 ++ 15 files changed, 57 insertions(+), 38 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index 1d780649..7a2e75d9 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -603,14 +603,15 @@ public: * Depending on the value of the @p free argument, the paints are either freed or retained. * So if you need to update paint properties while maintaining the existing scene structure, you can set @p free = false. * - * @param[in] free If @c true, the memory occupied by paints is deallocated, otherwise it is not. + * @param[in] paints If @c true, The memory occupied by paints is deallocated; otherwise, the paints will be retained on the canvas. + * @param[in] buffer If @c true, the canvas target buffer is cleared with a zero value. * * @return Result::Success when succeed, Result::InsufficientCondition otherwise. * * @see Canvas::push() * @see Canvas::paints() */ - virtual Result clear(bool free = true) noexcept; + virtual Result clear(bool paints = true, bool buffer = true) noexcept; /** * @brief Request the canvas to update the paint objects. diff --git a/src/bindings/capi/thorvg_capi.h b/src/bindings/capi/thorvg_capi.h index 079bcb3a..eb04e449 100644 --- a/src/bindings/capi/thorvg_capi.h +++ b/src/bindings/capi/thorvg_capi.h @@ -614,18 +614,17 @@ TVG_DEPRECATED TVG_API Tvg_Result tvg_canvas_reserve(Tvg_Canvas* canvas, uint32_ * all paints should be released manually in order to avoid memory leaks. * * \param[in] canvas The Tvg_Canvas object to be cleared. -* \param[in] free If @c true the memory occupied by paints is deallocated, otherwise it is not. +* \param[in] paints If @c true, The memory occupied by paints is deallocated; otherwise, the paints will be retained on the canvas. +* \param[in] buffer If @c true the canvas target buffer is cleared with a zero value. * * \return Tvg_Result enumeration. * \retval TVG_RESULT_SUCCESS Succeed. * \retval TVG_RESULT_INVALID_ARGUMENT An invalid Tvg_Canvas pointer. * \retval TVG_RESULT_INSUFFICIENT_CONDITION An internal error. * -* \warning Please use the @p free argument only when you know how it works, otherwise it's not recommended. -* * \see tvg_canvas_destroy() */ -TVG_API Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas, bool free); +TVG_API Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas, bool paints, bool buffer); /*! diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp index 7e1e4c8a..13da22e4 100644 --- a/src/bindings/capi/tvgCapi.cpp +++ b/src/bindings/capi/tvgCapi.cpp @@ -93,10 +93,10 @@ TVG_API Tvg_Result tvg_canvas_reserve(Tvg_Canvas* canvas, uint32_t n) } -TVG_API Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas, bool free) +TVG_API Tvg_Result tvg_canvas_clear(Tvg_Canvas* canvas, bool paints, bool buffer) { if (!canvas) return TVG_RESULT_INVALID_ARGUMENT; - return (Tvg_Result) reinterpret_cast(canvas)->clear(free); + return (Tvg_Result) reinterpret_cast(canvas)->clear(paints, buffer); } diff --git a/src/examples/Capi.cpp b/src/examples/Capi.cpp index c8b132de..85863fa6 100644 --- a/src/examples/Capi.cpp +++ b/src/examples/Capi.cpp @@ -246,6 +246,7 @@ void transitCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress } //Draw the canvas + tvg_canvas_clear(canvas, false, true); tvg_canvas_draw(canvas); tvg_canvas_sync(canvas); diff --git a/src/renderer/gl_engine/tvgGlRenderTask.cpp b/src/renderer/gl_engine/tvgGlRenderTask.cpp index def3160d..14f3feda 100644 --- a/src/renderer/gl_engine/tvgGlRenderTask.cpp +++ b/src/renderer/gl_engine/tvgGlRenderTask.cpp @@ -111,11 +111,10 @@ void GlComposeTask::run() GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, getSelfFbo())); // clear this fbo - GLenum color_buffer = GL_COLOR_ATTACHMENT0; - const float transparent[] = {0.f, 0.f, 0.f, 0.f}; - - GL_CHECK(glDrawBuffers(1, &color_buffer)); - GL_CHECK(glClearBufferfv(GL_COLOR, 0, transparent)); + if (mClearBuffer) { + const float transparent[] = {0.f, 0.f, 0.f, 0.f}; + GL_CHECK(glClearBufferfv(GL_COLOR, 0, transparent)); + } for(uint32_t i = 0; i < mTasks.count; i++) { mTasks[i]->run(); diff --git a/src/renderer/gl_engine/tvgGlRenderTask.h b/src/renderer/gl_engine/tvgGlRenderTask.h index 4e00dadd..15735261 100644 --- a/src/renderer/gl_engine/tvgGlRenderTask.h +++ b/src/renderer/gl_engine/tvgGlRenderTask.h @@ -103,6 +103,8 @@ public: void run() override; + bool mClearBuffer = true; + protected: GLuint getTargetFbo() { return mTargetFbo; } diff --git a/src/renderer/gl_engine/tvgGlRenderer.cpp b/src/renderer/gl_engine/tvgGlRenderer.cpp index 9cdc85db..5ac33085 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.cpp +++ b/src/renderer/gl_engine/tvgGlRenderer.cpp @@ -49,8 +49,7 @@ static void _termEngine() bool GlRenderer::clear() { - //TODO: (Request) to clear target - // Will be adding glClearColor for input buffer + mClearBuffer = true; return true; } @@ -98,15 +97,17 @@ bool GlRenderer::sync() task->setSize(surface.w, surface.h); + task->mClearBuffer = mClearBuffer; + task->run(); mGpuBuffer->unbind(); - GL_CHECK(glDisable(GL_SCISSOR_TEST)); mRenderPassStack.clear(); mPoolIndex = 0; + mClearBuffer = false; delete task; diff --git a/src/renderer/gl_engine/tvgGlRenderer.h b/src/renderer/gl_engine/tvgGlRenderer.h index cff97d78..44d7db5b 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.h +++ b/src/renderer/gl_engine/tvgGlRenderer.h @@ -86,13 +86,16 @@ private: GLint mTargetFboId = 0; RenderRegion mViewport; - std::unique_ptr mGpuBuffer; + //TODO: remove all unique_ptr / replace the vector with tvg::Array + unique_ptr mGpuBuffer; vector> mPrograms; unique_ptr mRootTarget = {}; vector> mComposePool = {}; size_t mPoolIndex = 0; vector mRenderPassStack = {}; vector> mComposeStack = {}; + + bool mClearBuffer = true; }; #endif /* _TVG_GL_RENDERER_H_ */ diff --git a/src/renderer/tvgCanvas.cpp b/src/renderer/tvgCanvas.cpp index 53938309..029aeb34 100644 --- a/src/renderer/tvgCanvas.cpp +++ b/src/renderer/tvgCanvas.cpp @@ -49,9 +49,9 @@ Result Canvas::push(unique_ptr paint) noexcept } -Result Canvas::clear(bool free) noexcept +Result Canvas::clear(bool paints, bool buffer) noexcept { - return pImpl->clear(free); + return pImpl->clear(paints, buffer); } diff --git a/src/renderer/tvgCanvas.h b/src/renderer/tvgCanvas.h index 323c85f2..e2a9b788 100644 --- a/src/renderer/tvgCanvas.h +++ b/src/renderer/tvgCanvas.h @@ -45,22 +45,19 @@ struct Canvas::Impl //make it sure any deffered jobs if (renderer) renderer->sync(); - clearPaints(true); + clearPaints(); delete(renderer); } - void clearPaints(bool free) + void clearPaints() { - if (free) { - for (auto paint : paints) { - P(paint)->unref(); - if (paint->pImpl->dispose(*renderer) && P(paint)->refCnt == 0) { - delete(paint); - } + for (auto paint : paints) { + P(paint)->unref(); + if (paint->pImpl->dispose(*renderer) && P(paint)->refCnt == 0) { + delete(paint); } - paints.clear(); } - drawing = false; + paints.clear(); } Result push(unique_ptr paint) @@ -76,12 +73,16 @@ struct Canvas::Impl return update(p, true); } - Result clear(bool free) + Result clear(bool paints, bool buffer) { - //Clear render target - if (!renderer || !renderer->clear()) return Result::InsufficientCondition; + if (drawing) return Result::InsufficientCondition; - clearPaints(free); + //Clear render target + if (buffer) { + if (!renderer || !renderer->clear()) return Result::InsufficientCondition; + } + + if (paints) clearPaints(); return Result::Success; } diff --git a/src/renderer/wg_engine/tvgWgRenderer.cpp b/src/renderer/wg_engine/tvgWgRenderer.cpp index 5cee42c3..65131c22 100644 --- a/src/renderer/wg_engine/tvgWgRenderer.cpp +++ b/src/renderer/wg_engine/tvgWgRenderer.cpp @@ -242,6 +242,7 @@ ColorSpace WgRenderer::colorSpace() { } bool WgRenderer::clear() { + mClearBuffer = true; return true; } @@ -274,9 +275,13 @@ bool WgRenderer::sync() { WGPURenderPassColorAttachment colorAttachment{}; colorAttachment.view = backBufferView; colorAttachment.resolveTarget = nullptr; - colorAttachment.loadOp = WGPULoadOp_Clear; + if (mClearBuffer) { + colorAttachment.loadOp = WGPULoadOp_Clear + colorAttachment.clearValue = {0, 0, 0, 0}; + } else { + colorAttachment.loadOp = WGPULoadOp_Load; + } colorAttachment.storeOp = WGPUStoreOp_Store; - colorAttachment.clearValue = { 0.0f, 0.0f, 0.0f, 1.0 }; // render pass descriptor WGPURenderPassDescriptor renderPassDesc{}; renderPassDesc.nextInChain = nullptr; @@ -351,6 +356,9 @@ bool WgRenderer::sync() { wgpuSwapChainPresent(mSwapChain); mRenderDatas.clear(); + + mClearBuffer = false; + return true; } diff --git a/src/renderer/wg_engine/tvgWgRenderer.h b/src/renderer/wg_engine/tvgWgRenderer.h index 93cd880d..7b00eafa 100644 --- a/src/renderer/wg_engine/tvgWgRenderer.h +++ b/src/renderer/wg_engine/tvgWgRenderer.h @@ -87,6 +87,8 @@ private: WgGeometryData mGeometryDataWindow; WgPipelineBindGroupEmpty mPipelineBindGroupEmpty; WgPipelineBindGroupStroke mPipelineBindGroupStroke; + + bool mClearBuffer; }; #endif /* _TVG_WG_RENDERER_H_ */ diff --git a/test/capi/capiSwCanvas.cpp b/test/capi/capiSwCanvas.cpp index b031487f..5074df95 100644 --- a/test/capi/capiSwCanvas.cpp +++ b/test/capi/capiSwCanvas.cpp @@ -94,7 +94,7 @@ TEST_CASE("Canvas draw", "[capiSwCanvas]") REQUIRE(tvg_canvas_draw(canvas) == TVG_RESULT_SUCCESS); REQUIRE(tvg_canvas_sync(canvas) == TVG_RESULT_SUCCESS); - REQUIRE(tvg_canvas_clear(canvas, true) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_canvas_clear(canvas, true, true) == TVG_RESULT_SUCCESS); Tvg_Paint* paint2 = tvg_shape_new(); REQUIRE(paint); @@ -129,11 +129,11 @@ TEST_CASE("Canvas update, clear and reuse", "[capiSwCanvas]") REQUIRE(tvg_canvas_update_paint(canvas, paint) == TVG_RESULT_SUCCESS); //negative - REQUIRE(tvg_canvas_clear(canvas, false) == TVG_RESULT_INSUFFICIENT_CONDITION); + REQUIRE(tvg_canvas_clear(canvas, false, true) == TVG_RESULT_INSUFFICIENT_CONDITION); uint32_t buffer[25]; REQUIRE(tvg_swcanvas_set_target(canvas, buffer, 5, 5, 5, TVG_COLORSPACE_ARGB8888) == TVG_RESULT_SUCCESS); - REQUIRE(tvg_canvas_clear(canvas, false) == TVG_RESULT_SUCCESS); + REQUIRE(tvg_canvas_clear(canvas, false, true) == TVG_RESULT_SUCCESS); REQUIRE(tvg_canvas_destroy(canvas) == TVG_RESULT_SUCCESS); diff --git a/test/images/tag.tvg b/test/images/tag.tvg index 95ae2447ef8f0e9d112589422fb75ae5a77143a0..97a70bc8fe8c41a60811d82da3a5f5c4b62a4564 100644 GIT binary patch delta 3327 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 diff --git a/test/testSwCanvasBase.cpp b/test/testSwCanvasBase.cpp index f778b376..66c542e4 100644 --- a/test/testSwCanvasBase.cpp +++ b/test/testSwCanvasBase.cpp @@ -169,6 +169,8 @@ TEST_CASE("Update", "[tvgSwCanvasBase]") REQUIRE(canvas->update() == Result::Success); REQUIRE(canvas->draw() == Result::Success); REQUIRE(canvas->update() == Result::InsufficientCondition); + REQUIRE(canvas->clear() == Result::InsufficientCondition); + REQUIRE(canvas->sync() == Result::Success); REQUIRE(canvas->clear() == Result::Success);