diff options
| -rw-r--r-- | util/sokol_debugtext.h | 244 | ||||
| -rw-r--r-- | util/sokol_gl.h | 2 |
2 files changed, 179 insertions, 67 deletions
diff --git a/util/sokol_debugtext.h b/util/sokol_debugtext.h index 85321f3a..42964623 100644 --- a/util/sokol_debugtext.h +++ b/util/sokol_debugtext.h @@ -60,6 +60,15 @@ sdtx_setup(&(sdtx_desc_t){ ... }); + To see any warnings and errors, you should always install a logging callback. + The easiest way is via sokol_log.h: + + #include "sokol_log.h" + + sdtx_setup(&(sdtx_desc_t){ + .logger.func = slog_func, + }); + --- configure sokol-debugtext by populating the sdtx_desc_t struct: .context_pool_size (default: 8) @@ -429,26 +438,47 @@ If no overrides are provided, malloc and free will be used. - LOG FUNCTION OVERRIDE - ===================== - You can override the log function at initialization time like this: + ERROR REPORTING AND LOGGING + =========================== + To get any logging information at all you need to provide a logging callback in the setup call, + the easiest way is to use sokol_log.h: + + #include "sokol_log.h" + + sdtx_setup(&(sdtx_desc_t){ + // ... + .logger.func = slog_func + }); - void my_log(const char* message, void* user_data) { - printf("sdtx says: \s\n", message); + To override logging with your own callback, first write a logging function like this: + + void my_log(const char* tag, // e.g. 'sdtx' + uint32_t log_level, // 0=panic, 1=error, 2=warn, 3=info + uint32_t log_item_id, // SDTX_LOGITEM_* + const char* message_or_null, // a message string, may be nullptr in release mode + uint32_t line_nr, // line number in sokol_debugtext.h + const char* filename_or_null, // source filename, may be nullptr in release mode + void* user_data) + { + ... } - ... - sdtx_setup(&(sdtx_desc_t){ - // ... - .logger = { - .log_cb = my_log, - .user_data = ..., - } - }); - ... + ...and then setup sokol-debugtext like this: + + sdtx_setup(&(sdtx_desc_t){ + .logger = { + .func = my_log, + .user_data = my_user_data, + } + }); + + The provided logging function must be reentrant (e.g. be callable from + different threads). + + If you don't want to provide your own custom logger it is highly recommended to use + the standard logger in sokol_log.h instead, otherwise you won't see any warnings or + errors. - If no overrides are provided, puts will be used on most platforms. - On Android, __android_log_write will be used instead. LICENSE ======= @@ -508,6 +538,45 @@ extern "C" { #endif +/* + sdtx_log_item_t + + Log items are defined via X-Macros, and expanded to an + enum 'sdtx_log_item' - and in debug mode only - corresponding strings. + + Used as parameter in the logging callback. +*/ +#define _SDTX_LOG_ITEMS \ + _SDTX_LOGITEM_XMACRO(OK) \ + _SDTX_LOGITEM_XMACRO(ADD_COMMIT_LISTENER_FAILED) \ + _SDTX_LOGITEM_XMACRO(COMMAND_BUFFER_FULL) \ + _SDTX_LOGITEM_XMACRO(CONTEXT_POOL_EXHAUSTED) \ + _SDTX_LOGITEM_XMACRO(CANNOT_DESTROY_DEFAULT_CONTEXT) \ + +#define _SDTX_LOGITEM_XMACRO(item) SDTX_LOGITEM_##item, +typedef enum sdtx_log_item_t { + _SDTX_LOG_ITEMS +} sdtx_log_item_t; +#undef _SDTX_LOGITEM_XMACRO + +/* + sdtx_logger_t + + Used in sdtx_desc_t to provide a custom logging and error reporting + callback to sokol-debugtext. +*/ +typedef struct sdtx_logger_t { + void (*func)( + const char* tag, // always "sdtx" + uint32_t log_level, // 0=panic, 1=error, 2=warning, 3=info + uint32_t log_item_id, // SDTX_LOGITEM_* + const char* message_or_null, // a message string, may be nullptr in release mode + uint32_t line_nr, // line number in sokol_debugtext.h + const char* filename_or_null, // source filename, may be nullptr in release mode + void* user_data); + void* user_data; +} sdtx_logger_t; + /* a rendering context handle */ typedef struct sdtx_context { uint32_t id; } sdtx_context; @@ -599,17 +668,6 @@ typedef struct sdtx_allocator_t { } sdtx_allocator_t; /* - sdtx_logger_t - - Used in sdtx_desc_t to provide custom log callbacks to sokol_debugtext.h. - Default behavior is SOKOL_LOG(message). -*/ -typedef struct sdtx_logger_t { - void (*log_cb)(const char* message, void* user_data); - void* user_data; -} sdtx_logger_t; - -/* sdtx_desc_t Describes the sokol-debugtext API initialization parameters. Passed @@ -631,7 +689,7 @@ typedef struct sdtx_desc_t { 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_logger_t logger; // optional log override functions (default: SOKOL_LOG(message)) + sdtx_logger_t logger; // optional log override function (default: NO LOGGING) } sdtx_desc_t; /* initialization/shutdown */ @@ -703,7 +761,14 @@ inline sdtx_context sdtx_make_context(const sdtx_context_desc_t& desc) { return #endif #endif /* SOKOL_DEBUGTEXT_INCLUDED */ -/*-- IMPLEMENTATION ----------------------------------------------------------*/ +// ██╗███╗ ███╗██████╗ ██╗ ███████╗███╗ ███╗███████╗███╗ ██╗████████╗ █████╗ ████████╗██╗ ██████╗ ███╗ ██╗ +// ██║████╗ ████║██╔══██╗██║ ██╔════╝████╗ ████║██╔════╝████╗ ██║╚══██╔══╝██╔══██╗╚══██╔══╝██║██╔═══██╗████╗ ██║ +// ██║██╔████╔██║██████╔╝██║ █████╗ ██╔████╔██║█████╗ ██╔██╗ ██║ ██║ ███████║ ██║ ██║██║ ██║██╔██╗ ██║ +// ██║██║╚██╔╝██║██╔═══╝ ██║ ██╔══╝ ██║╚██╔╝██║██╔══╝ ██║╚██╗██║ ██║ ██╔══██║ ██║ ██║██║ ██║██║╚██╗██║ +// ██║██║ ╚═╝ ██║██║ ███████╗███████╗██║ ╚═╝ ██║███████╗██║ ╚████║ ██║ ██║ ██║ ██║ ██║╚██████╔╝██║ ╚████║ +// ╚═╝╚═╝ ╚═╝╚═╝ ╚══════╝╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ +// +// >>implementation #ifdef SOKOL_DEBUGTEXT_IMPL #define SOKOL_DEBUGTEXT_IMPL_INCLUDED (1) @@ -729,21 +794,6 @@ inline sdtx_context sdtx_make_context(const sdtx_context_desc_t& desc) { return #define SOKOL_ASSERT(c) assert(c) #endif -#if !defined(SOKOL_DEBUG) - #define SDTX_LOG(s) -#else - #define SDTX_LOG(s) _sdtx_log(s) - #ifndef SOKOL_LOG - #if defined(__ANDROID__) - #include <android/log.h> - #define SOKOL_LOG(s) __android_log_write(ANDROID_LOG_INFO, "SOKOL_DEBUGTEXT", s) - #else - #include <stdio.h> - #define SOKOL_LOG(s) puts(s) - #endif - #endif -#endif - #ifndef SOKOL_UNREACHABLE #define SOKOL_UNREACHABLE SOKOL_ASSERT(false) #endif @@ -3498,6 +3548,15 @@ static const char* _sdtx_fs_src_dummy = ""; #error "Please define one of SOKOL_GLCORE33, SOKOL_GLES2, SOKOL_GLES3, SOKOL_D3D11, SOKOL_METAL, SOKOL_WGPU or SOKOL_DUMMY_BACKEND!" #endif +// ███████╗████████╗██████╗ ██╗ ██╗ ██████╗████████╗███████╗ +// ██╔════╝╚══██╔══╝██╔══██╗██║ ██║██╔════╝╚══██╔══╝██╔════╝ +// ███████╗ ██║ ██████╔╝██║ ██║██║ ██║ ███████╗ +// ╚════██║ ██║ ██╔══██╗██║ ██║██║ ██║ ╚════██║ +// ███████║ ██║ ██║ ██║╚██████╔╝╚██████╗ ██║ ███████║ +// ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝ +// +// +// >>structs typedef struct { uint32_t id; sg_resource_state state; @@ -3573,8 +3632,54 @@ typedef struct { } _sdtx_t; static _sdtx_t _sdtx; -/*=== MEMORY HELPERS =========================================================*/ +// ██╗ ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ +// ██║ ██╔═══██╗██╔════╝ ██╔════╝ ██║████╗ ██║██╔════╝ +// ██║ ██║ ██║██║ ███╗██║ ███╗██║██╔██╗ ██║██║ ███╗ +// ██║ ██║ ██║██║ ██║██║ ██║██║██║╚██╗██║██║ ██║ +// ███████╗╚██████╔╝╚██████╔╝╚██████╔╝██║██║ ╚████║╚██████╔╝ +// ╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ +// +// >>logging +#if defined(SOKOL_DEBUG) +#define _SDTX_LOGITEM_XMACRO(item) #item, +static const char* _sdtx_log_messages[] = { + _SDTX_LOG_ITEMS +}; +#undef _SDTX_LOGITEM_XMACRO +#endif // SOKOL_DEBUG + +#define _SDTX_PANIC(code) _sdtx_log(SDTX_LOGITEM_ ##code, 0, __LINE__) +#define _SDTX_ERROR(code) _sdtx_log(SDTX_LOGITEM_ ##code, 1, __LINE__) +#define _SDTX_WARN(code) _sdtx_log(SDTX_LOGITEM_ ##code, 2, __LINE__) +#define _SDTX_INFO(code) _sdtx_log(SDTX_LOGITEM_ ##code, 3, __LINE__) + +static void _sdtx_log(sdtx_log_item_t log_item, uint32_t log_level, uint32_t line_nr) { + if (_sdtx.desc.logger.func) { + #if defined(SOKOL_DEBUG) + const char* filename = __FILE__; + const char* message = _sdtx_log_messages[log_item]; + #else + const char* filename = 0; + const char* message = 0; + #endif + _sdtx.desc.logger.func("sdtx", log_level, log_item, message, line_nr, filename, _sdtx.desc.logger.user_data); + } + else { + // for log level PANIC it would be 'undefined behaviour' to continue + if (log_level == 0) { + abort(); + } + } +} +// ███╗ ███╗███████╗███╗ ███╗ ██████╗ ██████╗ ██╗ ██╗ +// ████╗ ████║██╔════╝████╗ ████║██╔═══██╗██╔══██╗╚██╗ ██╔╝ +// ██╔████╔██║█████╗ ██╔████╔██║██║ ██║██████╔╝ ╚████╔╝ +// ██║╚██╔╝██║██╔══╝ ██║╚██╔╝██║██║ ██║██╔══██╗ ╚██╔╝ +// ██║ ╚═╝ ██║███████╗██║ ╚═╝ ██║╚██████╔╝██║ ██║ ██║ +// ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ +// +// >>memory static void _sdtx_clear(void* ptr, size_t size) { SOKOL_ASSERT(ptr && (size > 0)); memset(ptr, 0, size); @@ -3608,18 +3713,14 @@ static void _sdtx_free(void* ptr) { } } -#if defined(SOKOL_DEBUG) -static void _sdtx_log(const char* msg) { - SOKOL_ASSERT(msg); - if (_sdtx.desc.logger.log_cb) { - _sdtx.desc.logger.log_cb(msg, _sdtx.desc.logger.user_data); - } else { - SOKOL_LOG(msg); - } -} -#endif - -/*=== CONTEXT POOL ===========================================================*/ +// ██████╗ ██████╗ ███╗ ██╗████████╗███████╗██╗ ██╗████████╗ ██████╗ ██████╗ ██████╗ ██╗ +// ██╔════╝██╔═══██╗████╗ ██║╚══██╔══╝██╔════╝╚██╗██╔╝╚══██╔══╝ ██╔══██╗██╔═══██╗██╔═══██╗██║ +// ██║ ██║ ██║██╔██╗ ██║ ██║ █████╗ ╚███╔╝ ██║ ██████╔╝██║ ██║██║ ██║██║ +// ██║ ██║ ██║██║╚██╗██║ ██║ ██╔══╝ ██╔██╗ ██║ ██╔═══╝ ██║ ██║██║ ██║██║ +// ╚██████╗╚██████╔╝██║ ╚████║ ██║ ███████╗██╔╝ ██╗ ██║ ██║ ╚██████╔╝╚██████╔╝███████╗ +// ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝ +// +// >>context pool static void _sdtx_init_pool(_sdtx_pool_t* pool, int num) { SOKOL_ASSERT(pool && (num >= 1)); /* slot 0 is reserved for the 'invalid id', so bump the pool size by 1 */ @@ -3853,9 +3954,7 @@ static void _sdtx_init_context(sdtx_context ctx_id, const sdtx_context_desc_t* i ctx->color = _SDTX_DEFAULT_COLOR; if (!sg_add_commit_listener(_sdtx_make_commit_listener(ctx))) { - // FIXME: this should actually result in an invalid context, - // fix this when proper error logging/reporting is added - SDTX_LOG("sokol_debugtext.h: failed to add sokol-gfx commit listener"); + _SDTX_ERROR(ADD_COMMIT_LISTENER_FAILED); } sg_pop_debug_group(); } @@ -3889,6 +3988,15 @@ static bool _sdtx_is_default_context(sdtx_context ctx_id) { return ctx_id.id == SDTX_DEFAULT_CONTEXT.id; } +// ███╗ ███╗██╗███████╗ ██████╗ +// ████╗ ████║██║██╔════╝██╔════╝ +// ██╔████╔██║██║███████╗██║ +// ██║╚██╔╝██║██║╚════██║██║ +// ██║ ╚═╝ ██║██║███████║╚██████╗ +// ╚═╝ ╚═╝╚═╝╚══════╝ ╚═════╝ +// +// >>misc + /* unpack linear 8x8 bits-per-pixel font data into 2D byte-per-pixel texture data */ static void _sdtx_unpack_font(const sdtx_font_desc_t* font_desc, uint8_t* out_pixels) { SOKOL_ASSERT(font_desc->data.ptr); @@ -4065,7 +4173,7 @@ static _sdtx_command_t* _sdtx_next_command(_sdtx_context_t* ctx) { return &ctx->commands.ptr[ctx->commands.next++]; } else { - SDTX_LOG("sokol_debugtext.h: command buffer full"); + _SDTX_ERROR(COMMAND_BUFFER_FULL); return 0; } } @@ -4191,8 +4299,14 @@ static sdtx_desc_t _sdtx_desc_defaults(const sdtx_desc_t* desc) { return res; } -/*=== PUBLIC API FUNCTIONS ===================================================*/ - +// ██████╗ ██╗ ██╗██████╗ ██╗ ██╗ ██████╗ +// ██╔══██╗██║ ██║██╔══██╗██║ ██║██╔════╝ +// ██████╔╝██║ ██║██████╔╝██║ ██║██║ +// ██╔═══╝ ██║ ██║██╔══██╗██║ ██║██║ +// ██║ ╚██████╔╝██████╔╝███████╗██║╚██████╗ +// ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ +// +// >>public SOKOL_API_IMPL void sdtx_setup(const sdtx_desc_t* desc) { SOKOL_ASSERT(desc); _sdtx_clear(&_sdtx, sizeof(_sdtx)); @@ -4254,7 +4368,7 @@ SOKOL_API_IMPL sdtx_context sdtx_make_context(const sdtx_context_desc_t* desc) { _sdtx_init_context(ctx_id, desc); } else { - SDTX_LOG("sokol_debugtext.h: context pool exhausted!"); + _SDTX_ERROR(CONTEXT_POOL_EXHAUSTED); } return ctx_id; } @@ -4262,7 +4376,7 @@ SOKOL_API_IMPL sdtx_context sdtx_make_context(const sdtx_context_desc_t* desc) { SOKOL_API_IMPL void sdtx_destroy_context(sdtx_context ctx_id) { SOKOL_ASSERT(_SDTX_INIT_COOKIE == _sdtx.init_cookie); if (_sdtx_is_default_context(ctx_id)) { - SDTX_LOG("sokol_debugtext.h: cannot destroy default context"); + _SDTX_ERROR(CANNOT_DESTROY_DEFAULT_CONTEXT); return; } _sdtx_destroy_context(ctx_id); diff --git a/util/sokol_gl.h b/util/sokol_gl.h index aae8355e..5d5ae18d 100644 --- a/util/sokol_gl.h +++ b/util/sokol_gl.h @@ -2916,8 +2916,6 @@ static void _sgl_init_context(sgl_context ctx_id, const sgl_context_desc_t* in_d def_pip_desc.depth.write_enabled = true; ctx->def_pip = _sgl_make_pipeline(&def_pip_desc, &ctx->desc); if (!sg_add_commit_listener(_sgl_make_commit_listener(ctx))) { - // FIXME: this should actually result in an invalid context, - // fix this when proper error logging/reporting is added _SGL_ERROR(ADD_COMMIT_LISTENER_FAILED); } sg_pop_debug_group(); |