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 95ae2447..97a70bc8 100644 Binary files a/test/images/tag.tvg and b/test/images/tag.tvg differ 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);