aboutsummaryrefslogtreecommitdiff
path: root/util/sokol_debugtext.h
diff options
context:
space:
mode:
authorAndre Weissflog <floooh@gmail.com>2022-05-15 17:20:52 +0200
committerGitHub <noreply@github.com>2022-05-15 17:20:52 +0200
commitb2e593137f6a5a1e8383d7f4ee891879470986af (patch)
treed81cebda1b790da450e6584f124a51bc14b3c08f /util/sokol_debugtext.h
parentd634c620b207d34be5a7423771e911c6bd76063b (diff)
Add memory allocator callbacks to sokol headers. (#662)
Diffstat (limited to 'util/sokol_debugtext.h')
-rw-r--r--util/sokol_debugtext.h157
1 files changed, 115 insertions, 42 deletions
diff --git a/util/sokol_debugtext.h b/util/sokol_debugtext.h
index a87d9775..99524cc5 100644
--- a/util/sokol_debugtext.h
+++ b/util/sokol_debugtext.h
@@ -28,8 +28,6 @@
SOKOL_VSNPRINTF - the function name of an alternative vsnprintf() function (default: vsnprintf)
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
- SOKOL_MALLOC(s) - your own malloc function (default: malloc(s))
- SOKOL_FREE(p) - your own free function (default: free(p))
SOKOL_DEBUGTEXT_API_DECL - public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_DEBUGTEXT_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
@@ -370,6 +368,34 @@
Character tiles that haven't been defined in the font will be rendered
as a solid 8x8 quad.
+
+ MEMORY ALLOCATION OVERRIDE
+ ==========================
+ You can override the memory allocation functions at initialization time
+ like this:
+
+ void* my_alloc(size_t size, void* user_data) {
+ return malloc(size);
+ }
+
+ void my_free(void* ptr, void* user_data) {
+ free(ptr);
+ }
+
+ ...
+ sdtx_setup(&(sdtx_desc_t){
+ // ...
+ .allocator = {
+ .alloc = my_alloc,
+ .free = my_free,
+ .user_data = ...;
+ }
+ });
+ ...
+
+ If no overrides are provided, malloc and free will be used.
+
+
LICENSE
=======
zlib/libpng license
@@ -504,6 +530,23 @@ typedef struct sdtx_context_desc_t {
} sdtx_context_desc_t;
/*
+ sdtx_allocator_t
+
+ Used in sdtx_desc_t to provide custom memory-alloc and -free functions
+ to sokol_debugtext.h. If memory management should be overridden, both the
+ alloc and free function must be provided (e.g. it's not valid to
+ override one function but not the other).
+*/
+typedef void*(*sdtx_malloc_t)(size_t size, void* user_data);
+typedef void(*sdtx_free_t)(void* ptr, void* user_data);
+
+typedef struct sdtx_allocator_t {
+ sdtx_malloc_t alloc;
+ sdtx_free_t free;
+ void* user_data;
+} sdtx_allocator_t;
+
+/*
sdtx_desc_t
Describes the sokol-debugtext API initialization parameters. Passed
@@ -524,6 +567,7 @@ typedef struct sdtx_desc_t {
int printf_buf_size; // size of internal buffer for snprintf(), default: 4096
sdtx_font_desc_t fonts[SDTX_MAX_FONTS]; // up to 8 fonts descriptions
sdtx_context_desc_t context; // the default context creation parameters
+ sdtx_allocator_t allocator; // optional memory allocation overrides (default: malloc/free)
} sdtx_desc_t;
/* initialization/shutdown */
@@ -593,9 +637,14 @@ inline sdtx_context sdtx_make_context(const sdtx_context_desc_t& desc) { return
#ifdef SOKOL_DEBUGTEXT_IMPL
#define SOKOL_DEBUGTEXT_IMPL_INCLUDED (1)
+#if defined(SOKOL_MALLOC) || defined(SOKOL_CALLOC) || defined(SOKOL_FREE)
+#error "SOKOL_MALLOC/CALLOC/FREE macros are no longer supported, please use sdtx_desc_t.allocator to override memory allocation functions"
+#endif
+
#include <string.h> // memset
#include <math.h> // fmodf
#include <stdarg.h> // for vsnprintf
+#include <stdlib.h> // malloc/free
#ifndef SOKOL_API_IMPL
#define SOKOL_API_IMPL
@@ -609,11 +658,6 @@ inline sdtx_context sdtx_make_context(const sdtx_context_desc_t& desc) { return
#include <assert.h>
#define SOKOL_ASSERT(c) assert(c)
#endif
-#ifndef SOKOL_MALLOC
- #include <stdlib.h>
- #define SOKOL_MALLOC(s) malloc(s)
- #define SOKOL_FREE(p) free(p)
-#endif
#ifndef SOKOL_LOG
#ifdef SOKOL_DEBUG
#include <stdio.h>
@@ -3434,6 +3478,41 @@ typedef struct {
} _sdtx_t;
static _sdtx_t _sdtx;
+/*=== MEMORY HELPERS =========================================================*/
+
+static void _sdtx_clear(void* ptr, size_t size) {
+ SOKOL_ASSERT(ptr && (size > 0));
+ memset(ptr, 0, size);
+}
+
+static void* _sdtx_malloc(size_t size) {
+ SOKOL_ASSERT(size > 0);
+ void* ptr;
+ if (_sdtx.desc.allocator.alloc) {
+ ptr = _sdtx.desc.allocator.alloc(size, _sdtx.desc.allocator.user_data);
+ }
+ else {
+ ptr = malloc(size);
+ }
+ SOKOL_ASSERT(ptr);
+ return ptr;
+}
+
+static void* _sdtx_malloc_clear(size_t size) {
+ void* ptr = _sdtx_malloc(size);
+ _sdtx_clear(ptr, size);
+ return ptr;
+}
+
+static void _sdtx_free(void* ptr) {
+ if (_sdtx.desc.allocator.free) {
+ _sdtx.desc.allocator.free(ptr, _sdtx.desc.allocator.user_data);
+ }
+ else {
+ free(ptr);
+ }
+}
+
/*=== CONTEXT POOL ===========================================================*/
static void _sdtx_init_pool(_sdtx_pool_t* pool, int num) {
SOKOL_ASSERT(pool && (num >= 1));
@@ -3442,12 +3521,9 @@ static void _sdtx_init_pool(_sdtx_pool_t* pool, int num) {
pool->queue_top = 0;
/* generation counters indexable by pool slot index, slot 0 is reserved */
size_t gen_ctrs_size = sizeof(uint32_t) * (size_t)pool->size;
- pool->gen_ctrs = (uint32_t*) SOKOL_MALLOC(gen_ctrs_size);
- SOKOL_ASSERT(pool->gen_ctrs);
- memset(pool->gen_ctrs, 0, gen_ctrs_size);
+ pool->gen_ctrs = (uint32_t*) _sdtx_malloc_clear(gen_ctrs_size);
/* it's not a bug to only reserve 'num' here */
- pool->free_queue = (int*) SOKOL_MALLOC(sizeof(int) * (size_t)num);
- SOKOL_ASSERT(pool->free_queue);
+ pool->free_queue = (int*) _sdtx_malloc_clear(sizeof(int) * (size_t)num);
/* never allocate the zero-th pool item since the invalid id is 0 */
for (int i = pool->size-1; i >= 1; i--) {
pool->free_queue[pool->queue_top++] = i;
@@ -3457,10 +3533,10 @@ static void _sdtx_init_pool(_sdtx_pool_t* pool, int num) {
static void _sdtx_discard_pool(_sdtx_pool_t* pool) {
SOKOL_ASSERT(pool);
SOKOL_ASSERT(pool->free_queue);
- SOKOL_FREE(pool->free_queue);
+ _sdtx_free(pool->free_queue);
pool->free_queue = 0;
SOKOL_ASSERT(pool->gen_ctrs);
- SOKOL_FREE(pool->gen_ctrs);
+ _sdtx_free(pool->gen_ctrs);
pool->gen_ctrs = 0;
pool->size = 0;
pool->queue_top = 0;
@@ -3501,14 +3577,12 @@ static void _sdtx_setup_context_pool(const sdtx_desc_t* desc) {
SOKOL_ASSERT((desc->context_pool_size > 0) && (desc->context_pool_size < _SDTX_MAX_POOL_SIZE));
_sdtx_init_pool(&_sdtx.context_pool.pool, desc->context_pool_size);
size_t pool_byte_size = sizeof(_sdtx_context_t) * (size_t)_sdtx.context_pool.pool.size;
- _sdtx.context_pool.contexts = (_sdtx_context_t*) SOKOL_MALLOC(pool_byte_size);
- SOKOL_ASSERT(_sdtx.context_pool.contexts);
- memset(_sdtx.context_pool.contexts, 0, pool_byte_size);
+ _sdtx.context_pool.contexts = (_sdtx_context_t*) _sdtx_malloc_clear(pool_byte_size);
}
static void _sdtx_discard_context_pool(void) {
SOKOL_ASSERT(_sdtx.context_pool.contexts);
- SOKOL_FREE(_sdtx.context_pool.contexts);
+ _sdtx_free(_sdtx.context_pool.contexts);
_sdtx.context_pool.contexts = 0;
_sdtx_discard_pool(&_sdtx.context_pool.pool);
}
@@ -3603,13 +3677,12 @@ static void _sdtx_init_context(sdtx_context ctx_id, const sdtx_context_desc_t* i
const int max_vertices = 6 * ctx->desc.char_buf_size;
const size_t vbuf_size = (size_t)max_vertices * sizeof(_sdtx_vertex_t);
- ctx->vertices = (_sdtx_vertex_t*) SOKOL_MALLOC(vbuf_size);
- SOKOL_ASSERT(ctx->vertices);
+ ctx->vertices = (_sdtx_vertex_t*) _sdtx_malloc(vbuf_size);
ctx->cur_vertex_ptr = ctx->vertices;
ctx->max_vertex_ptr = ctx->vertices + max_vertices;
sg_buffer_desc vbuf_desc;
- memset(&vbuf_desc, 0, sizeof(vbuf_desc));
+ _sdtx_clear(&vbuf_desc, sizeof(vbuf_desc));
vbuf_desc.size = vbuf_size;
vbuf_desc.type = SG_BUFFERTYPE_VERTEXBUFFER;
vbuf_desc.usage = SG_USAGE_STREAM;
@@ -3618,7 +3691,7 @@ static void _sdtx_init_context(sdtx_context ctx_id, const sdtx_context_desc_t* i
SOKOL_ASSERT(SG_INVALID_ID != ctx->vbuf.id);
sg_pipeline_desc pip_desc;
- memset(&pip_desc, 0, sizeof(pip_desc));
+ _sdtx_clear(&pip_desc, sizeof(pip_desc));
pip_desc.layout.buffers[0].stride = sizeof(_sdtx_vertex_t);
pip_desc.layout.attrs[0].format = SG_VERTEXFORMAT_FLOAT2;
pip_desc.layout.attrs[1].format = SG_VERTEXFORMAT_USHORT2N;
@@ -3651,7 +3724,7 @@ static void _sdtx_destroy_context(sdtx_context ctx_id) {
_sdtx_context_t* ctx = _sdtx_lookup_context(ctx_id.id);
if (ctx) {
if (ctx->vertices) {
- SOKOL_FREE(ctx->vertices);
+ _sdtx_free(ctx->vertices);
ctx->vertices = 0;
ctx->cur_vertex_ptr = 0;
ctx->max_vertex_ptr = 0;
@@ -3660,7 +3733,7 @@ static void _sdtx_destroy_context(sdtx_context ctx_id) {
sg_destroy_buffer(ctx->vbuf);
sg_destroy_pipeline(ctx->pip);
sg_pop_debug_group();
- memset(ctx, 0, sizeof(*ctx));
+ _sdtx_clear(ctx, sizeof(*ctx));
_sdtx_pool_free_index(&_sdtx.context_pool.pool, _sdtx_slot_index(ctx_id.id));
}
}
@@ -3690,14 +3763,13 @@ static void _sdtx_setup_common(void) {
/* common printf formatting buffer */
_sdtx.fmt_buf_size = (uint32_t) _sdtx.desc.printf_buf_size + 1;
- _sdtx.fmt_buf = (char*) SOKOL_MALLOC(_sdtx.fmt_buf_size);
- SOKOL_ASSERT(_sdtx.fmt_buf);
+ _sdtx.fmt_buf = (char*) _sdtx_malloc_clear(_sdtx.fmt_buf_size);
sg_push_debug_group("sokol-debugtext");
/* common shader for all contexts */
sg_shader_desc shd_desc;
- memset(&shd_desc, 0, sizeof(shd_desc));
+ _sdtx_clear(&shd_desc, sizeof(shd_desc));
shd_desc.label = "sokol-debugtext-shader";
shd_desc.attrs[0].name = "position";
shd_desc.attrs[1].name = "texcoord0";
@@ -3758,7 +3830,7 @@ static void _sdtx_setup_common(void) {
/* create font texture */
sg_image_desc img_desc;
- memset(&img_desc, 0, sizeof(img_desc));
+ _sdtx_clear(&img_desc, sizeof(img_desc));
img_desc.width = 256 * 8;
img_desc.height = SDTX_MAX_FONTS * 8;
img_desc.pixel_format = SG_PIXELFORMAT_R8;
@@ -3778,7 +3850,7 @@ static void _sdtx_discard_common(void) {
sg_destroy_image(_sdtx.font_img);
sg_destroy_shader(_sdtx.shader);
if (_sdtx.fmt_buf) {
- SOKOL_FREE(_sdtx.fmt_buf);
+ _sdtx_free(_sdtx.fmt_buf);
_sdtx.fmt_buf = 0;
}
sg_pop_debug_group();
@@ -3868,27 +3940,28 @@ static inline void _sdtx_put_char(_sdtx_context_t* ctx, char c) {
}
}
-static sdtx_desc_t _sdtx_desc_defaults(const sdtx_desc_t* in_desc) {
- sdtx_desc_t desc = *in_desc;
- desc.context_pool_size = _sdtx_def(desc.context_pool_size, _SDTX_DEFAULT_CONTEXT_POOL_SIZE);
- desc.printf_buf_size = _sdtx_def(desc.printf_buf_size, _SDTX_DEFAULT_PRINTF_BUF_SIZE);
+static sdtx_desc_t _sdtx_desc_defaults(const sdtx_desc_t* desc) {
+ SOKOL_ASSERT((desc->allocator.alloc && desc->allocator.free) || (!desc->allocator.alloc && !desc->allocator.free));
+ sdtx_desc_t res = *desc;
+ res.context_pool_size = _sdtx_def(res.context_pool_size, _SDTX_DEFAULT_CONTEXT_POOL_SIZE);
+ res.printf_buf_size = _sdtx_def(res.printf_buf_size, _SDTX_DEFAULT_PRINTF_BUF_SIZE);
for (int i = 0; i < SDTX_MAX_FONTS; i++) {
- if (desc.fonts[i].data.ptr) {
- desc.fonts[i].last_char = _sdtx_def(desc.fonts[i].last_char, 255);
+ if (res.fonts[i].data.ptr) {
+ res.fonts[i].last_char = _sdtx_def(res.fonts[i].last_char, 255);
}
}
- desc.context = _sdtx_context_desc_defaults(&desc.context);
- SOKOL_ASSERT(desc.context_pool_size > 0);
- SOKOL_ASSERT(desc.printf_buf_size > 0);
- SOKOL_ASSERT(desc.context.char_buf_size > 0);
- return desc;
+ res.context = _sdtx_context_desc_defaults(&res.context);
+ SOKOL_ASSERT(res.context_pool_size > 0);
+ SOKOL_ASSERT(res.printf_buf_size > 0);
+ SOKOL_ASSERT(res.context.char_buf_size > 0);
+ return res;
}
/*=== PUBLIC API FUNCTIONS ===================================================*/
SOKOL_API_IMPL void sdtx_setup(const sdtx_desc_t* desc) {
SOKOL_ASSERT(desc);
- memset(&_sdtx, 0, sizeof(_sdtx));
+ _sdtx_clear(&_sdtx, sizeof(_sdtx));
_sdtx.init_cookie = _SDTX_INIT_COOKIE;
_sdtx.desc = _sdtx_desc_defaults(desc);
_sdtx_setup_context_pool(&_sdtx.desc);
@@ -4195,7 +4268,7 @@ SOKOL_API_IMPL void sdtx_draw(void) {
int vbuf_offset = sg_append_buffer(ctx->vbuf, &range);
sg_apply_pipeline(ctx->pip);
sg_bindings bindings;
- memset(&bindings, 0, sizeof(bindings));
+ _sdtx_clear(&bindings, sizeof(bindings));
bindings.vertex_buffers[0] = ctx->vbuf;
bindings.vertex_buffer_offsets[0] = vbuf_offset;
bindings.fs_images[0] = _sdtx.font_img;