diff options
| author | Andre Weissflog <floooh@gmail.com> | 2022-11-14 15:07:28 +0100 |
|---|---|---|
| committer | Andre Weissflog <floooh@gmail.com> | 2022-11-14 15:07:28 +0100 |
| commit | 7e7a691938a3e5c9f2b15f80ba8169c414929c8a (patch) | |
| tree | 16400fbadef01fc65f0a94f085f7519d36db7d15 /util/sokol_debugtext.h | |
| parent | ba67a7b36dd5f9ce7a88872db37b977df7d1a23b (diff) | |
sokol_debugtext.h: render layers more wip
Diffstat (limited to 'util/sokol_debugtext.h')
| -rw-r--r-- | util/sokol_debugtext.h | 228 |
1 files changed, 179 insertions, 49 deletions
diff --git a/util/sokol_debugtext.h b/util/sokol_debugtext.h index cf35cc5e..cd31175b 100644 --- a/util/sokol_debugtext.h +++ b/util/sokol_debugtext.h @@ -725,9 +725,10 @@ inline sdtx_context sdtx_make_context(const sdtx_context_desc_t& desc) { return #define _sdtx_def(val, def) (((val) == 0) ? (def) : (val)) #define _SDTX_INIT_COOKIE (0xACBAABCA) +#define _SDTX_DEFAULT_MAX_COMMANDS (4096) #define _SDTX_DEFAULT_CONTEXT_POOL_SIZE (8) -#define _SDTX_DEFAULT_CHAR_BUF_SIZE (1<<12) -#define _SDTX_DEFAULT_PRINTF_BUF_SIZE (1<<12) +#define _SDTX_DEFAULT_CHAR_BUF_SIZE (4096) +#define _SDTX_DEFAULT_PRINTF_BUF_SIZE (4096) #define _SDTX_DEFAULT_CANVAS_WIDTH (640) #define _SDTX_DEFAULT_CANVAS_HEIGHT (480) #define _SDTX_DEFAULT_TAB_WIDTH (4) @@ -3486,7 +3487,7 @@ typedef struct { } _sdtx_vertex_t; typedef struct { - int layer; + int layer_id; int first_vertex; int num_vertices; } _sdtx_command_t; @@ -3494,10 +3495,18 @@ typedef struct { typedef struct { _sdtx_slot_t slot; sdtx_context_desc_t desc; - _sdtx_vertex_t* cur_vertex_ptr; - const _sdtx_vertex_t* max_vertex_ptr; - _sdtx_vertex_t* vertices; - _sdtx_command_t* commands; + uint32_t frame_id; + uint32_t update_frame_id; + struct { + int cap; + int next; + _sdtx_vertex_t* ptr; + } vertices; + struct { + int cap; + int next; + _sdtx_command_t* ptr; + } commands; sg_buffer vbuf; sg_pipeline pip; int cur_font; @@ -3719,6 +3728,7 @@ static sdtx_context _sdtx_alloc_context(void) { static sdtx_context_desc_t _sdtx_context_desc_defaults(const sdtx_context_desc_t* desc) { sdtx_context_desc_t res = *desc; + res.max_commands = _sdtx_def(res.max_commands, _SDTX_DEFAULT_MAX_COMMANDS); res.char_buf_size = _sdtx_def(res.char_buf_size, _SDTX_DEFAULT_CHAR_BUF_SIZE); res.canvas_width = _sdtx_def(res.canvas_width, _SDTX_DEFAULT_CANVAS_WIDTH); res.canvas_height = _sdtx_def(res.canvas_height, _SDTX_DEFAULT_CANVAS_HEIGHT); @@ -3730,6 +3740,30 @@ static sdtx_context_desc_t _sdtx_context_desc_defaults(const sdtx_context_desc_t return res; } +static void _sdtx_set_layer(_sdtx_context_t* ctx, int layer_id); +static void _sdtx_rewind(_sdtx_context_t* ctx) { + SOKOL_ASSERT(ctx); + ctx->frame_id++; + ctx->vertices.next = 0; + ctx->commands.next = 0; + _sdtx_set_layer(ctx, 0); + ctx->cur_font = 0; + ctx->pos.x = 0.0f; + ctx->pos.y = 0.0f; +} + +static void _sdtx_commit_listener(void* userdata) { + _sdtx_context_t* ctx = _sdtx_lookup_context((uint32_t)(uintptr_t)userdata); + if (ctx) { + _sdtx_rewind(ctx); + } +} + +static sg_commit_listener _sdtx_make_commit_listener(_sdtx_context_t* ctx) { + sg_commit_listener listener = { _sdtx_commit_listener, (void*)(uintptr_t)(ctx->slot.id) }; + return listener; +} + static void _sdtx_init_context(sdtx_context ctx_id, const sdtx_context_desc_t* in_desc) { sg_push_debug_group("sokol-debugtext"); @@ -3737,12 +3771,16 @@ static void _sdtx_init_context(sdtx_context ctx_id, const sdtx_context_desc_t* i _sdtx_context_t* ctx = _sdtx_lookup_context(ctx_id.id); SOKOL_ASSERT(ctx); ctx->desc = _sdtx_context_desc_defaults(in_desc); + // NOTE: frame_id must be non-zero, so that updates trigger in first frame + ctx->frame_id = 1; + + ctx->vertices.cap = 6 * ctx->desc.char_buf_size; + const size_t vbuf_size = (size_t)ctx->vertices.cap * sizeof(_sdtx_vertex_t); + ctx->vertices.ptr = (_sdtx_vertex_t*) _sdtx_malloc(vbuf_size); - 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*) _sdtx_malloc(vbuf_size); - ctx->cur_vertex_ptr = ctx->vertices; - ctx->max_vertex_ptr = ctx->vertices + max_vertices; + ctx->commands.cap = ctx->desc.max_commands; + ctx->commands.ptr = (_sdtx_command_t*) _sdtx_malloc((size_t)ctx->commands.cap * sizeof(_sdtx_command_t)); + _sdtx_set_layer(ctx, 0); sg_buffer_desc vbuf_desc; _sdtx_clear(&vbuf_desc, sizeof(vbuf_desc)); @@ -3780,21 +3818,33 @@ static void _sdtx_init_context(sdtx_context ctx_id, const sdtx_context_desc_t* i ctx->tab_width = (float) ctx->desc.tab_width; 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"); + } sg_pop_debug_group(); } static void _sdtx_destroy_context(sdtx_context ctx_id) { _sdtx_context_t* ctx = _sdtx_lookup_context(ctx_id.id); if (ctx) { - if (ctx->vertices) { - _sdtx_free(ctx->vertices); - ctx->vertices = 0; - ctx->cur_vertex_ptr = 0; - ctx->max_vertex_ptr = 0; + if (ctx->vertices.ptr) { + _sdtx_free(ctx->vertices.ptr); + ctx->vertices.ptr = 0; + ctx->vertices.cap = 0; + ctx->vertices.next = 0; + } + if (ctx->commands.ptr) { + _sdtx_free(ctx->commands.ptr); + ctx->commands.ptr = 0; + ctx->commands.cap = 0; + ctx->commands.next = 0; } sg_push_debug_group("sokol_debugtext"); sg_destroy_buffer(ctx->vbuf); sg_destroy_pipeline(ctx->pip); + sg_remove_commit_listener(_sdtx_make_commit_listener(ctx)); sg_pop_debug_group(); _sdtx_clear(ctx, sizeof(*ctx)); _sdtx_pool_free_index(&_sdtx.context_pool.pool, _sdtx_slot_index(ctx_id.id)); @@ -3919,17 +3969,17 @@ static void _sdtx_discard_common(void) { sg_pop_debug_group(); } -static inline uint32_t _sdtx_pack_rgbab(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { +static uint32_t _sdtx_pack_rgbab(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { return (uint32_t)(((uint32_t)a<<24)|((uint32_t)b<<16)|((uint32_t)g<<8)|r); } -static inline float _sdtx_clamp(float v, float lo, float hi) { +static float _sdtx_clamp(float v, float lo, float hi) { if (v < lo) return lo; else if (v > hi) return hi; else return v; } -static inline uint32_t _sdtx_pack_rgbaf(float r, float g, float b, float a) { +static uint32_t _sdtx_pack_rgbaf(float r, float g, float b, float a) { uint8_t r_u8 = (uint8_t) (_sdtx_clamp(r, 0.0f, 1.0f) * 255.0f); uint8_t g_u8 = (uint8_t) (_sdtx_clamp(g, 0.0f, 1.0f) * 255.0f); uint8_t b_u8 = (uint8_t) (_sdtx_clamp(b, 0.0f, 1.0f) * 255.0f); @@ -3937,7 +3987,7 @@ static inline uint32_t _sdtx_pack_rgbaf(float r, float g, float b, float a) { return _sdtx_pack_rgbab(r_u8, g_u8, b_u8, a_u8); } -static inline void _sdtx_ctrl_char(_sdtx_context_t* ctx, uint8_t c) { +static void _sdtx_ctrl_char(_sdtx_context_t* ctx, uint8_t c) { switch (c) { case '\r': ctx->pos.x = 0.0f; @@ -3955,8 +4005,72 @@ static inline void _sdtx_ctrl_char(_sdtx_context_t* ctx, uint8_t c) { } } -static inline void _sdtx_draw_char(_sdtx_context_t* ctx, uint8_t c) { - if ((ctx->cur_vertex_ptr + 6) <= ctx->max_vertex_ptr) { +static _sdtx_vertex_t* _sdtx_next_vertex(_sdtx_context_t* ctx) { + if ((ctx->vertices.next + 6) <= ctx->vertices.cap) { + _sdtx_vertex_t* vx = &ctx->vertices.ptr[ctx->vertices.next]; + ctx->vertices.next += 6; + return vx; + } + else { + return 0; + } +} + +static _sdtx_command_t* _sdtx_cur_command(_sdtx_context_t* ctx) { + if (ctx->commands.next > 0) { + return &ctx->commands.ptr[ctx->commands.next - 1]; + } + else { + return 0; + } +} + +static _sdtx_command_t* _sdtx_next_command(_sdtx_context_t* ctx) { + if (ctx->commands.next < ctx->commands.cap) { + return &ctx->commands.ptr[ctx->commands.next++]; + } + else { + SDTX_LOG("sokol_debugtext.h: command buffer full"); + return 0; + } +} + +static void _sdtx_set_layer(_sdtx_context_t* ctx, int layer_id) { + ctx->cur_layer_id = layer_id; + _sdtx_command_t* cur_cmd = _sdtx_cur_command(ctx); + if (cur_cmd) { + if ((cur_cmd->num_vertices == 0) || (cur_cmd->layer_id == layer_id)) { + // no vertices recorded in current draw command, or layer hasn't changed, can just reuse this + cur_cmd->layer_id = layer_id; + } + else { + // layer has changed, need to start a new draw command + _sdtx_command_t* next_cmd = _sdtx_next_command(ctx); + if (next_cmd) { + next_cmd->layer_id = layer_id; + next_cmd->first_vertex = cur_cmd->first_vertex + cur_cmd->num_vertices; + next_cmd->num_vertices = 0; + } + } + } + else { + // first draw command in frame + _sdtx_command_t* next_cmd = _sdtx_next_command(ctx); + if (next_cmd) { + next_cmd->layer_id = layer_id; + next_cmd->first_vertex = 0; + next_cmd->num_vertices = 0; + } + } +} + +static void _sdtx_render_char(_sdtx_context_t* ctx, uint8_t c) { + _sdtx_vertex_t* vx = _sdtx_next_vertex(ctx); + _sdtx_command_t* cmd = _sdtx_cur_command(ctx); + if (vx && cmd) { + // update vertex count in current draw command + cmd->num_vertices += 6; + const float x0 = (ctx->origin.x + ctx->pos.x) * ctx->glyph_size.x; const float y0 = (ctx->origin.y + ctx->pos.y) * ctx->glyph_size.y; const float x1 = x0 + ctx->glyph_size.x; @@ -3978,8 +4092,6 @@ static inline void _sdtx_draw_char(_sdtx_context_t* ctx, uint8_t c) { const uint32_t color = ctx->color; // write 6 vertices - _sdtx_vertex_t* vx = ctx->cur_vertex_ptr; - vx->x=x0; vx->y=y0; vx->u = u0; vx->v = v0; vx->color = color; vx++; vx->x=x1; vx->y=y0; vx->u = u1; vx->v = v0; vx->color = color; vx++; vx->x=x1; vx->y=y1; vx->u = u1; vx->v = v1; vx->color = color; vx++; @@ -3987,22 +4099,51 @@ static inline void _sdtx_draw_char(_sdtx_context_t* ctx, uint8_t c) { vx->x=x0; vx->y=y0; vx->u = u0; vx->v = v0; vx->color = color; vx++; vx->x=x1; vx->y=y1; vx->u = u1; vx->v = v1; vx->color = color; vx++; vx->x=x0; vx->y=y1; vx->u = u0; vx->v = v1; vx->color = color; vx++; - - ctx->cur_vertex_ptr = vx; } ctx->pos.x += 1.0f; } -static inline void _sdtx_put_char(_sdtx_context_t* ctx, char c) { +static void _sdtx_put_char(_sdtx_context_t* ctx, char c) { uint8_t c_u8 = (uint8_t)c; if (c_u8 <= 32) { _sdtx_ctrl_char(ctx, c_u8); } else { - _sdtx_draw_char(ctx, c_u8); + _sdtx_render_char(ctx, c_u8); + } +} + +SOKOL_API_IMPL void _sdtx_draw_layer(_sdtx_context_t* ctx, int layer_id) { + SOKOL_ASSERT(_SDTX_INIT_COOKIE == _sdtx.init_cookie); + SOKOL_ASSERT(ctx); + if ((ctx->vertices.next > 0) && (ctx->commands.next > 0)) { + sg_push_debug_group("sokol-debugtext"); + + if (ctx->update_frame_id != ctx->frame_id) { + ctx->update_frame_id = ctx->frame_id; + const sg_range range = { ctx->vertices.ptr, (size_t)ctx->vertices.next * sizeof(_sdtx_vertex_t) }; + sg_update_buffer(ctx->vbuf, &range); + } + + sg_apply_pipeline(ctx->pip); + sg_bindings bindings; + _sdtx_clear(&bindings, sizeof(bindings)); + bindings.vertex_buffers[0] = ctx->vbuf; + bindings.fs_images[0] = _sdtx.font_img; + sg_apply_bindings(&bindings); + for (int cmd_index = 0; cmd_index < ctx->commands.next; cmd_index++) { + const _sdtx_command_t* cmd = &ctx->commands.ptr[cmd_index]; + if (cmd->layer_id != layer_id) { + continue; + } + SOKOL_ASSERT((cmd->num_vertices % 6) == 0); + sg_draw(cmd->first_vertex, cmd->num_vertices, 1); + } + sg_pop_debug_group(); } } + 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; @@ -4121,6 +4262,14 @@ SOKOL_API_IMPL sdtx_context sdtx_default_context(void) { return SDTX_DEFAULT_CONTEXT; } +SOKOL_API_IMPL void sdtx_layer(int layer_id) { + SOKOL_ASSERT(_SDTX_INIT_COOKIE == _sdtx.init_cookie); + _sdtx_context_t* ctx = _sdtx.cur_ctx; + if (ctx) { + _sdtx_set_layer(ctx, layer_id); + } +} + SOKOL_API_IMPL void sdtx_font(int font_index) { SOKOL_ASSERT(_SDTX_INIT_COOKIE == _sdtx.init_cookie); SOKOL_ASSERT((font_index >= 0) && (font_index < SDTX_MAX_FONTS)); @@ -4323,26 +4472,7 @@ SOKOL_API_IMPL void sdtx_draw(void) { SOKOL_ASSERT(_SDTX_INIT_COOKIE == _sdtx.init_cookie); _sdtx_context_t* ctx = _sdtx.cur_ctx; if (ctx) { - const int num_verts = (int) (ctx->cur_vertex_ptr - ctx->vertices); - if (num_verts > 0) { - SOKOL_ASSERT((num_verts % 6) == 0); - sg_push_debug_group("sokol-debugtext"); - const sg_range range = { ctx->vertices, (size_t)num_verts * sizeof(_sdtx_vertex_t) }; - int vbuf_offset = sg_append_buffer(ctx->vbuf, &range); - sg_apply_pipeline(ctx->pip); - sg_bindings 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; - sg_apply_bindings(&bindings); - sg_draw(0, num_verts, 1); - sg_pop_debug_group(); - } - ctx->cur_vertex_ptr = ctx->vertices; - ctx->cur_font = 0; - ctx->pos.x = 0.0f; - ctx->pos.y = 0.0f; + _sdtx_draw_layer(ctx, 0); } } |