renderer/canvas: ++exceptional handling.

do not allow change the target if the condition is not satisfied.
This commit is contained in:
Hermet Park 2024-06-23 18:40:29 +09:00
parent 60212747b5
commit 9fb8a49d52
7 changed files with 24 additions and 8 deletions

View file

@ -1685,11 +1685,13 @@ public:
* @retval Result::Success When succeed.
* @retval Result::MemoryCorruption When casting in the internal function implementation failed.
* @retval Result::InvalidArguments In case no valid pointer is provided or the width, or the height or the stride is zero.
* @retval Result::InsufficientCondition if the canvas is performing rendering. Please ensure the canvas is synced.
* @retval Result::NonSupport In case the software engine is not supported.
*
* @warning Do not access @p buffer during Canvas::push() - Canvas::sync(). It should not be accessed while the engine is writing on it.
*
* @see Canvas::viewport()
* @see Canvas::sync()
*/
Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Colorspace cs) noexcept;
@ -1752,10 +1754,13 @@ public:
* @param[in] w The width (in pixels) of the raster image.
* @param[in] h The height (in pixels) of the raster image.
*
* @warning This API is experimental and not officially supported. It may be modified or removed in future versions.
* @warning Drawing on the main surface is currently not permitted. If the identifier (@p id) is set to @c 0, the operation will be aborted.
* @retval Result::Success When succeed.
* @retval Result::MemoryCorruption When casting in the internal function implementation failed.
* @retval Result::InsufficientCondition if the canvas is performing rendering. Please ensure the canvas is synced.
* @retval Result::NonSupport In case the gl engine is not supported.
*
* @see Canvas::viewport()
* @see Canvas::sync()
*
* @note Currently, this only allows the GL_RGBA8 color space format.
* @note Experimental API
@ -1795,10 +1800,13 @@ public:
* @param[in] instance WGPUInstance, context for all other wgpu objects.
* @param[in] surace WGPUSurface, handle to a presentable surface.
*
* @warning Please do not use it, this API is not official one. It could be modified in the next version.
* @retval Result::InsufficientCondition if the canvas is performing rendering. Please ensure the canvas is synced.
* @retval Result::NonSupport In case the wg engine is not supported.
*
* @note Experimental API
*
* @see Canvas::viewport()
* @see Canvas::sync()
*/
Result target(void* instance, void* surface, uint32_t w, uint32_t h) noexcept;

View file

@ -452,6 +452,7 @@ TVG_API Tvg_Canvas* tvg_swcanvas_create(void);
* \retval TVG_RESULT_SUCCESS Succeed.
* \retval TVG_RESULT_MEMORY_CORRUPTION Casting in the internal function implementation failed.
* \retval TVG_RESULT_INVALID_ARGUMENTS An invalid canvas or buffer pointer passed or one of the @p stride, @p w or @p h being zero.
* \retval TVG_RESULT_INSUFFICIENT_CONDITION if the canvas is performing rendering. Please ensure the canvas is synced.
* \retval TVG_RESULT_NOT_SUPPORTED The software engine is not supported.
*
* \warning Do not access @p buffer during tvg_canvas_draw() - tvg_canvas_sync(). It should not be accessed while the engine is writing on it.

View file

@ -26,10 +26,10 @@
#include "tvgPaint.h"
enum Status : uint8_t {Synced = 0, Updating, Drawing};
struct Canvas::Impl
{
enum Status : uint8_t {Synced = 0, Updating, Drawing};
list<Paint*> paints;
RenderMethod* renderer;
RenderRegion vport = {0, 0, INT32_MAX, INT32_MAX};

View file

@ -62,6 +62,8 @@ GlCanvas::~GlCanvas()
Result GlCanvas::target(int32_t id, uint32_t w, uint32_t h) noexcept
{
#ifdef THORVG_GL_RASTER_SUPPORT
if (Canvas::pImpl->status != Status::Synced) return Result::InsufficientCondition;
//We know renderer type, avoid dynamic_cast for performance.
auto renderer = static_cast<GlRenderer*>(Canvas::pImpl->renderer);
if (!renderer) return Result::MemoryCorruption;

View file

@ -82,6 +82,8 @@ Result SwCanvas::mempool(MempoolPolicy policy) noexcept
Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Colorspace cs) noexcept
{
#ifdef THORVG_SW_RASTER_SUPPORT
if (Canvas::pImpl->status != Status::Synced) return Result::InsufficientCondition;
//We know renderer type, avoid dynamic_cast for performance.
auto renderer = static_cast<SwRenderer*>(Canvas::pImpl->renderer);
if (!renderer) return Result::MemoryCorruption;

View file

@ -57,9 +57,9 @@ WgCanvas::~WgCanvas()
Result WgCanvas::target(void* instance, void* surface, uint32_t w, uint32_t h) noexcept
{
#ifdef THORVG_WG_RASTER_SUPPORT
if (!instance) return Result::InvalidArguments;
if (!surface) return Result::InvalidArguments;
if ((w == 0) || (h == 0)) return Result::InvalidArguments;
if (Canvas::pImpl->status != Status::Synced) return Result::InsufficientCondition;
if (!instance || !surface || (w == 0) || (h == 0)) return Result::InvalidArguments;
//We know renderer type, avoid dynamic_cast for performance.
auto renderer = static_cast<WgRenderer*>(Canvas::pImpl->renderer);

View file

@ -131,6 +131,9 @@ TEST_CASE("Canvas update, clear and reuse", "[capiSwCanvas]")
//negative
REQUIRE(tvg_canvas_clear(canvas, false, true) == TVG_RESULT_INSUFFICIENT_CONDITION);
//make it sure sync before changing the target
REQUIRE(tvg_canvas_sync(canvas) == TVG_RESULT_SUCCESS);
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, true) == TVG_RESULT_SUCCESS);