From 3cc9d308ddea7e0f5385413a3adc43e6b8236b25 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Philippe=20Bruy=C3=A8re?= Date: Wed, 16 Mar 2022 13:25:28 +0100 Subject: [PATCH] always return valid pointer for surface/context/pattern --- include/vkvg.h | 18 ++++++++-- src/vkvg_context.c | 46 +++++++++++++++++++----- src/vkvg_context_internal.h | 2 +- src/vkvg_fonts.h | 5 --- src/vkvg_internal.h | 12 +++++++ src/vkvg_pattern.c | 71 +++++++++++++++++++++++++++---------- src/vkvg_pattern.h | 5 ++- src/vkvg_surface.c | 31 +++++++++++----- src/vkvg_surface_internal.c | 7 ++-- src/vkvg_surface_internal.h | 4 +-- 10 files changed, 149 insertions(+), 52 deletions(-) diff --git a/include/vkvg.h b/include/vkvg.h index dfc1497..1b720e2 100644 --- a/include/vkvg.h +++ b/include/vkvg.h @@ -700,6 +700,9 @@ const void* vkvg_get_device_requirements (VkPhysicalDeviceFeatures* pEnabledFeat * @{ */ /** * @brief Create a new vkvg surface. + * + * This method will always return a valid pointer. + * * @param dev The vkvg device used for creating the surface. * @param width Width in pixel of the surface to create. * @param height Height in pixel of the surface to create. @@ -710,6 +713,7 @@ VkvgSurface vkvg_surface_create (VkvgDevice dev, uint32_t width, uint32_t height /** * @brief Create a new vkvg surface by loading an image file. * The resulting surface will have the same dimension as the supplied image. + * This method will always return a valid pointer. * * @param dev The vkvg device used for creating the surface. * @param filePath The path of the image to load for creating the surface. @@ -719,6 +723,7 @@ vkvg_public VkvgSurface vkvg_surface_create_from_image (VkvgDevice dev, const char* filePath); /** * @brief Create a new vkvg surface using an existing vulkan texture as backend. + * This method will always return a valid pointer. * @param dev The vkvg device used for creating the surface. * @param vkhImg The VkhImage to use as the backend texture for drawing operations. * @return A new surface, or null if an error occured. @@ -747,7 +752,7 @@ uint32_t vkvg_surface_get_reference_count (VkvgSurface surf); vkvg_public void vkvg_surface_destroy (VkvgSurface surf); /** - * @brief Query the current status of the surface + * @brief Query the current status of the surface. * @param The vkvg surface to query the status for. * @return The current surface status. */ @@ -875,6 +880,7 @@ typedef enum _vkvg_operator { * @brief Create a new vkvg context used for drawing on surfaces. * * Creates a new #VkvgContext with all graphics state parameters set to default values and with surf as a target surface. + * This method will always return a valid pointer even if memory allocation failed. * @remark This function references surf, so you can immediately call #vkvg_surface_destroy() on it if you don't need to maintain a separate reference to it. * @param surf The target surface of the drawing operations. * @return A new #VkvgContext or null if an error occured. @@ -1799,7 +1805,15 @@ void vkvg_text_run_get_glyph_position (VkvgText textRun, * and which may have special configuration for filtering and border repeat. * * @{ */ - +/** + * @brief Get pattern current status. + * + * Querry the current status of a pattern. + * @param pat A valid pattern handle. + * @return The current status of the pattern. + */ +vkvg_public +vkvg_status_t vkvg_pattern_status (VkvgPattern pat); /** * @brief add reference * diff --git a/src/vkvg_context.c b/src/vkvg_context.c index 5b4a693..67e8b1d 100644 --- a/src/vkvg_context.c +++ b/src/vkvg_context.c @@ -109,10 +109,8 @@ VkvgContext vkvg_create(VkvgSurface surf) LOG(VKVG_LOG_INFO, "CREATE Context: ctx = %p; surf = %p\n", ctx, surf); - if (ctx==NULL) { - dev->status = VKVG_STATUS_NO_MEMORY; - return NULL; - } + if (!ctx) + return (VkvgContext)&_no_mem_status; ctx->pSurf = surf; @@ -255,6 +253,9 @@ void _clear_context (VkvgContext ctx) { void vkvg_destroy (VkvgContext ctx) { + if (ctx->status) + return; + ctx->references--; if (ctx->references > 0) return; @@ -308,7 +309,7 @@ void vkvg_destroy (VkvgContext ctx) } void vkvg_set_opacity (VkvgContext ctx, float opacity) { if (ctx->status) - return; + return; if (EQUF(ctx->pushConsts.opacity, opacity)) return; @@ -318,16 +319,21 @@ void vkvg_set_opacity (VkvgContext ctx, float opacity) { ctx->pushCstDirty = true; } float vkvg_get_opacity (VkvgContext ctx) { - return ctx->pushConsts.opacity; + if (ctx->status) + return 0; + return ctx->pushConsts.opacity; } vkvg_status_t vkvg_status (VkvgContext ctx) { return ctx->status; } VkvgContext vkvg_reference (VkvgContext ctx) { - ctx->references++; + if (!ctx->status) + ctx->references++; return ctx; } uint32_t vkvg_get_reference_count (VkvgContext ctx) { + if (ctx->status) + return 0; return ctx->references; } void vkvg_new_sub_path (VkvgContext ctx){ @@ -531,7 +537,7 @@ bool vkvg_has_current_point (VkvgContext ctx) { return !_current_path_is_empty(ctx); } void vkvg_get_current_point (VkvgContext ctx, float* x, float* y) { - if (_current_path_is_empty(ctx)) { + if (ctx->status || _current_path_is_empty(ctx)) { *x = *y = 0; return; } @@ -1041,18 +1047,26 @@ void vkvg_set_source (VkvgContext ctx, VkvgPattern pat){ vkvg_pattern_reference (pat); } void vkvg_set_line_width (VkvgContext ctx, float width){ + if (ctx->status) + return; RECORD(ctx, VKVG_CMD_SET_LINE_WIDTH, width); ctx->lineWidth = width; } void vkvg_set_miter_limit (VkvgContext ctx, float limit){ + if (ctx->status) + return; RECORD(ctx, VKVG_CMD_SET_LINE_WIDTH, limit); ctx->miterLimit = limit; } void vkvg_set_line_cap (VkvgContext ctx, vkvg_line_cap_t cap){ + if (ctx->status) + return; RECORD(ctx, VKVG_CMD_SET_LINE_CAP, cap); ctx->lineCap = cap; } void vkvg_set_line_join (VkvgContext ctx, vkvg_line_join_t join){ + if (ctx->status) + return; RECORD(ctx, VKVG_CMD_SET_LINE_JOIN, join); ctx->lineJoin = join; } @@ -1071,15 +1085,21 @@ void vkvg_set_operator (VkvgContext ctx, vkvg_operator_t op){ _bind_draw_pipeline (ctx); } void vkvg_set_fill_rule (VkvgContext ctx, vkvg_fill_rule_t fr){ + if (ctx->status) + return; #ifndef __APPLE__ RECORD(ctx, VKVG_CMD_SET_FILL_RULE, fr); ctx->curFillRule = fr; #endif } vkvg_fill_rule_t vkvg_get_fill_rule (VkvgContext ctx){ + if (ctx->status) + return VKVG_FILL_RULE_NON_ZERO; return ctx->curFillRule; } float vkvg_get_line_width (VkvgContext ctx){ + if (ctx->status) + return 0; return ctx->lineWidth; } void vkvg_set_dash (VkvgContext ctx, const float* dashes, uint32_t num_dashes, float offset){ @@ -1096,6 +1116,8 @@ void vkvg_set_dash (VkvgContext ctx, const float* dashes, uint32_t num_dashes, f memcpy (ctx->dashes, dashes, sizeof(float) * ctx->dashCount); } void vkvg_get_dash (VkvgContext ctx, const float* dashes, uint32_t* num_dashes, float* offset){ + if (ctx->status) + return; *num_dashes = ctx->dashCount; *offset = ctx->dashOffset; if (ctx->dashCount == 0 || dashes == NULL) @@ -1105,15 +1127,23 @@ void vkvg_get_dash (VkvgContext ctx, const float* dashes, uint32_t* num_dashes, vkvg_line_cap_t vkvg_get_line_cap (VkvgContext ctx){ + if (ctx->status) + return (vkvg_line_cap_t)0; return ctx->lineCap; } vkvg_line_join_t vkvg_get_line_join (VkvgContext ctx){ + if (ctx->status) + return (vkvg_line_join_t)0; return ctx->lineJoin; } vkvg_operator_t vkvg_get_operator (VkvgContext ctx){ + if (ctx->status) + return (vkvg_operator_t)0; return ctx->curOperator; } VkvgPattern vkvg_get_source (VkvgContext ctx){ + if (ctx->status) + return NULL; vkvg_pattern_reference (ctx->pattern); return ctx->pattern; } diff --git a/src/vkvg_context_internal.h b/src/vkvg_context_internal.h index b82e7da..bd241ec 100644 --- a/src/vkvg_context_internal.h +++ b/src/vkvg_context_internal.h @@ -126,6 +126,7 @@ typedef struct _vkvg_context_save_t { } vkvg_context_save_t; typedef struct _vkvg_context_t { + vkvg_status_t status; uint32_t references; //reference count VkvgDevice dev; @@ -213,7 +214,6 @@ typedef struct _vkvg_context_t { push_constants pushConsts; VkvgPattern pattern; - vkvg_status_t status; vkvg_context_save_t* pSavedCtxs; //last ctx saved ptr uint8_t curSavBit; //current stencil bit used to save context, 6 bits used by stencil for save/restore diff --git a/src/vkvg_fonts.h b/src/vkvg_fonts.h index 4f1f4de..72710d5 100644 --- a/src/vkvg_fonts.h +++ b/src/vkvg_fonts.h @@ -60,11 +60,6 @@ #define FONT_NAME_MAX_SIZE 128 #include "vkvg_internal.h" -#include "vkvg.h" -#include "vkvg_buff.h" -#include "vkh.h" -#include "vectors.h" - //texture coordinates of one character in font cache array texture. typedef struct { diff --git a/src/vkvg_internal.h b/src/vkvg_internal.h index 120d5d4..c56424e 100644 --- a/src/vkvg_internal.h +++ b/src/vkvg_internal.h @@ -85,4 +85,16 @@ //30 seconds fence timeout #define VKVG_FENCE_TIMEOUT 30000000000 //#define VKVG_FENCE_TIMEOUT 10000 + +#include "vkvg.h" +#include "vkvg_buff.h" +#include "vkh.h" +#include "vectors.h" + +/*typedef struct { + vkvg_status_t status; +} _vkvg_no_mem_struct;*/ + +static vkvg_status_t _no_mem_status = VKVG_STATUS_NO_MEMORY; + #endif diff --git a/src/vkvg_pattern.c b/src/vkvg_pattern.c index ee902d4..ffc635e 100644 --- a/src/vkvg_pattern.c +++ b/src/vkvg_pattern.c @@ -27,16 +27,23 @@ VkvgPattern vkvg_pattern_create_for_surface (VkvgSurface surf){ VkvgPattern pat = (vkvg_pattern_t*)calloc(1, sizeof(vkvg_pattern_t)); + if (!pat) + return (VkvgPattern)&_no_mem_status; + pat->type = VKVG_PATTERN_TYPE_SURFACE; pat->extend = VKVG_EXTEND_NONE; pat->data = surf; - pat->references = 1; + vkvg_surface_reference (surf); + if (surf->status) + pat->status = surf->status; return pat; } vkvg_status_t vkvg_pattern_get_linear_points (VkvgPattern pat, float* x0, float* y0, float* x1, float* y1) { + if (pat->status) + return pat->status; if (pat->type != VKVG_PATTERN_TYPE_LINEAR) return VKVG_STATUS_PATTERN_TYPE_MISMATCH; @@ -49,6 +56,8 @@ vkvg_status_t vkvg_pattern_get_linear_points (VkvgPattern pat, float* x0, float* return VKVG_STATUS_SUCCESS; } vkvg_status_t vkvg_pattern_edit_linear (VkvgPattern pat, float x0, float y0, float x1, float y1){ + if (pat->status) + return pat->status; if (pat->type != VKVG_PATTERN_TYPE_LINEAR) return VKVG_STATUS_PATTERN_TYPE_MISMATCH; @@ -60,25 +69,25 @@ vkvg_status_t vkvg_pattern_edit_linear (VkvgPattern pat, float x0, float y0, flo VkvgPattern vkvg_pattern_create_linear (float x0, float y0, float x1, float y1){ VkvgPattern pat = (vkvg_pattern_t*)calloc(1, sizeof(vkvg_pattern_t)); if (!pat) - return NULL; + return (VkvgPattern)&_no_mem_status; pat->type = VKVG_PATTERN_TYPE_LINEAR; pat->extend = VKVG_EXTEND_NONE; pat->data = (void*)calloc(1,sizeof(vkvg_gradient_t)); - if (!pat->data) { - free (pat); - return NULL; - } - - vkvg_pattern_edit_linear(pat, x0, y0, x1, y1); - pat->references = 1; + if (pat->data) { + vkvg_pattern_edit_linear(pat, x0, y0, x1, y1); + pat->references = 1; + } else + pat->status = VKVG_STATUS_NO_MEMORY; return pat; } vkvg_status_t vkvg_pattern_edit_radial (VkvgPattern pat, float cx0, float cy0, float radius0, float cx1, float cy1, float radius1) { + if (pat->status) + return pat->status; if (pat->type != VKVG_PATTERN_TYPE_RADIAL) return VKVG_STATUS_PATTERN_TYPE_MISMATCH; @@ -104,30 +113,33 @@ VkvgPattern vkvg_pattern_create_radial (float cx0, float cy0, float radius0, float cx1, float cy1, float radius1){ VkvgPattern pat = (vkvg_pattern_t*)calloc(1, sizeof(vkvg_pattern_t)); if (!pat) - return NULL; + return (VkvgPattern)&_no_mem_status; pat->type = VKVG_PATTERN_TYPE_RADIAL; pat->extend = VKVG_EXTEND_NONE; pat->data = (void*)calloc(1,sizeof(vkvg_gradient_t)); - if (!pat->data) { - free (pat); - return NULL; - } - vkvg_pattern_edit_radial (pat, cx0, cy0, radius0, cx1, cy1, radius1); - - pat->references = 1; + if (pat->data) { + vkvg_pattern_edit_radial (pat, cx0, cy0, radius0, cx1, cy1, radius1); + pat->references = 1; + } else + pat->status = VKVG_STATUS_NO_MEMORY; return pat; } VkvgPattern vkvg_pattern_reference (VkvgPattern pat) { - pat->references++; + if (!pat->status) + pat->references++; return pat; } uint32_t vkvg_pattern_get_reference_count (VkvgPattern pat) { + if (pat->status) + return 0; return pat->references; } vkvg_status_t vkvg_pattern_add_color_stop (VkvgPattern pat, float offset, float r, float g, float b, float a) { + if (pat->status) + return pat->status; if (pat->type == VKVG_PATTERN_TYPE_SURFACE || pat->type == VKVG_PATTERN_TYPE_SOLID) return VKVG_STATUS_PATTERN_TYPE_MISMATCH; @@ -146,22 +158,34 @@ vkvg_status_t vkvg_pattern_add_color_stop (VkvgPattern pat, float offset, float grad->count++; } void vkvg_pattern_set_extend (VkvgPattern pat, vkvg_extend_t extend){ + if (pat->status) + return; pat->extend = extend; } void vkvg_pattern_set_filter (VkvgPattern pat, vkvg_filter_t filter){ + if (pat->status) + return; pat->filter = filter; } vkvg_extend_t vkvg_pattern_get_extend (VkvgPattern pat){ + if (pat->status) + return (vkvg_extend_t)0; return pat->extend; } vkvg_filter_t vkvg_pattern_get_filter (VkvgPattern pat){ + if (pat->status) + return (vkvg_filter_t)0; return pat->filter; } vkvg_pattern_type_t vkvg_pattern_get_type (VkvgPattern pat){ + if (pat->status) + return (vkvg_pattern_type_t)0; return pat->type; } vkvg_status_t vkvg_pattern_get_color_stop_count (VkvgPattern pat, uint32_t* count) { + if (pat->status) + return pat->status; if (pat->type == VKVG_PATTERN_TYPE_SURFACE || pat->type == VKVG_PATTERN_TYPE_SOLID) return VKVG_STATUS_PATTERN_TYPE_MISMATCH; vkvg_gradient_t* grad = (vkvg_gradient_t*)pat->data; @@ -170,6 +194,8 @@ vkvg_status_t vkvg_pattern_get_color_stop_count (VkvgPattern pat, uint32_t* coun } vkvg_status_t vkvg_pattern_get_color_stop_rgba (VkvgPattern pat, uint32_t index, float* offset, float* r, float* g, float* b, float* a) { + if (pat->status) + return pat->status; if (pat->type == VKVG_PATTERN_TYPE_SURFACE || pat->type == VKVG_PATTERN_TYPE_SOLID) return VKVG_STATUS_PATTERN_TYPE_MISMATCH; vkvg_gradient_t* grad = (vkvg_gradient_t*)pat->data; @@ -188,18 +214,27 @@ vkvg_status_t vkvg_pattern_get_color_stop_rgba (VkvgPattern pat, uint32_t index, return VKVG_STATUS_SUCCESS; } void vkvg_pattern_set_matrix (VkvgPattern pat, const vkvg_matrix_t* matrix) { + if (pat->status) + return; pat->matrix = *matrix; pat->hasMatrix = true; } void vkvg_pattern_get_matrix (VkvgPattern pat, vkvg_matrix_t* matrix) { + if (pat->status) + return; if (pat->hasMatrix) *matrix = pat->matrix; else *matrix = VKVG_IDENTITY_MATRIX; } +vkvg_status_t vkvg_pattern_status (VkvgPattern pat) { + return pat->status; +} void vkvg_pattern_destroy(VkvgPattern pat) { + if (pat->status) + return; pat->references--; if (pat->references > 0) return; diff --git a/src/vkvg_pattern.h b/src/vkvg_pattern.h index 2c5589f..e860012 100644 --- a/src/vkvg_pattern.h +++ b/src/vkvg_pattern.h @@ -23,17 +23,16 @@ #define VKVG_PATTERN_H #include "vkvg_internal.h" -#include "vkvg.h" -#include "vkh.h" typedef struct _vkvg_pattern_t { + vkvg_status_t status; + uint32_t references; vkvg_pattern_type_t type; vkvg_extend_t extend; vkvg_filter_t filter; vkvg_matrix_t matrix; bool hasMatrix; void* data; - uint32_t references; }vkvg_pattern_t; typedef struct _vkvg_gradient_t { diff --git a/src/vkvg_surface.c b/src/vkvg_surface.c index cae040a..05dc8dd 100644 --- a/src/vkvg_surface.c +++ b/src/vkvg_surface.c @@ -37,7 +37,7 @@ void vkvg_surface_clear (VkvgSurface surf) { } VkvgSurface vkvg_surface_create (VkvgDevice dev, uint32_t width, uint32_t height){ VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT); - if (!surf || surf->status) + if (surf->status) return surf; surf->width = MAX(1, width); @@ -52,7 +52,7 @@ VkvgSurface vkvg_surface_create (VkvgDevice dev, uint32_t width, uint32_t height } VkvgSurface vkvg_surface_create_for_VkhImage (VkvgDevice dev, void* vkhImg) { VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT); - if (!surf || surf->status) + if (surf->status) return surf; if (!vkhImg) { @@ -80,7 +80,7 @@ VkvgSurface vkvg_surface_create_for_VkhImage (VkvgDevice dev, void* vkhImg) { //TODO: it would be better to blit in original size and create ms final image with dest surf dims VkvgSurface vkvg_surface_create_from_bitmap (VkvgDevice dev, unsigned char* img, uint32_t width, uint32_t height) { VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT); - if (!surf || surf->status) + if (surf->status) return surf; if (!img || width <= 0 || height <= 0) { surf->status = VKVG_STATUS_INVALID_IMAGE; @@ -187,9 +187,9 @@ VkvgSurface vkvg_surface_create_from_image (VkvgDevice dev, const char* filePath h = 0, channels = 0; unsigned char *img = stbi_load(filePath, &w, &h, &channels, 4);//force 4 components per pixel - if (img == NULL){ - fprintf (stderr, "Could not load texture from %s, %s\n", filePath, stbi_failure_reason()); - return NULL; + if (!img){ + LOG(VKVG_LOG_ERR, "Could not load texture from %s, %s\n", filePath, stbi_failure_reason()); + return (VkvgSurface)&_no_mem_status; } VkvgSurface surf = vkvg_surface_create_from_bitmap(dev, img, (uint32_t)w, (uint32_t)h); @@ -201,6 +201,9 @@ VkvgSurface vkvg_surface_create_from_image (VkvgDevice dev, const char* filePath void vkvg_surface_destroy(VkvgSurface surf) { + if (surf->status) + return; + LOCK_SURFACE(surf) surf->references--; if (surf->references > 0) { @@ -225,12 +228,16 @@ void vkvg_surface_destroy(VkvgSurface surf) } VkvgSurface vkvg_surface_reference (VkvgSurface surf) { - LOCK_SURFACE(surf) - surf->references++; - UNLOCK_SURFACE(surf) + if (!surf->status) { + LOCK_SURFACE(surf) + surf->references++; + UNLOCK_SURFACE(surf) + } return surf; } uint32_t vkvg_surface_get_reference_count (VkvgSurface surf) { + if (surf->status) + return 0; return surf->references; } @@ -249,12 +256,18 @@ void vkvg_surface_resolve (VkvgSurface surf){ } VkFormat vkvg_surface_get_vk_format(VkvgSurface surf) { + if (surf->status) + return VK_FORMAT_UNDEFINED; return surf->format; } uint32_t vkvg_surface_get_width (VkvgSurface surf) { + if (surf->status) + return 0; return surf->width; } uint32_t vkvg_surface_get_height (VkvgSurface surf) { + if (surf->status) + return 0; return surf->height; } diff --git a/src/vkvg_surface_internal.c b/src/vkvg_surface_internal.c index 2076f7b..ffa5983 100644 --- a/src/vkvg_surface_internal.c +++ b/src/vkvg_surface_internal.c @@ -174,10 +174,9 @@ void _create_surface_images (VkvgSurface surf) { } VkvgSurface _create_surface (VkvgDevice dev, VkFormat format) { VkvgSurface surf = (vkvg_surface*)calloc(1,sizeof(vkvg_surface)); - if (!surf) { - dev->status = VKVG_STATUS_NO_MEMORY; - return NULL; - } + if (!surf) + return (VkvgSurface)&_no_mem_status; + surf->references = 1; if (dev->status != VKVG_STATUS_SUCCESS) { surf->status = VKVG_STATUS_DEVICE_ERROR; diff --git a/src/vkvg_surface_internal.h b/src/vkvg_surface_internal.h index e01092e..79b64e3 100644 --- a/src/vkvg_surface_internal.h +++ b/src/vkvg_surface_internal.h @@ -27,6 +27,8 @@ #include "vkh.h" typedef struct _vkvg_surface_t { + vkvg_status_t status; /**< Current status of surface, affected by last operation */ + uint32_t references; VkvgDevice dev; uint32_t width; uint32_t height; @@ -35,8 +37,6 @@ typedef struct _vkvg_surface_t { VkhImage img; VkhImage imgMS; VkhImage stencil; - uint32_t references; - vkvg_status_t status; /**< Current status of surface, affected by last operation */ bool new; mtx_t mutex; }vkvg_surface; -- 2.47.3