Skip to content

Commit ebedce9

Browse files
committed
Improve log rendering performance
Logs are now stored in a circular buffer rather then a shifting list of strings. This will improve the performance when adding logs but should not have that much impace since we don't do this on every frame. However the rendering of the logs has been improved to reduce the performance impact when generating textures for each log line on every frame.
1 parent f2dac6f commit ebedce9

File tree

3 files changed

+67
-59
lines changed

3 files changed

+67
-59
lines changed

src/gui.c

Lines changed: 52 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,26 @@
3636
#include "texturecache.h"
3737
#include "gui_util.h"
3838

39-
#define DEFAULT_LOG { NULL, LOG_LINES_COUNT, 0, 200 }
40-
#define DEFAULT_EVENT_MESSAGES { NULL, 5, 0, 200 }
39+
#define DEFAULT_EVENT_MESSAGES { NULL, 5, 0, LOG_LINES_MAX_LEN }
4140

4241
#define POS_Y_COLLECTABLES 64
4342
#define POS_Y_XPBAR 128
4443

4544
static struct LogData_t {
46-
char **log;
47-
unsigned int len;
48-
unsigned int count;
49-
unsigned int strlen;
50-
} log_data = DEFAULT_LOG;
45+
char log[LOG_LINES_COUNT][LOG_LINES_MAX_LEN];
46+
uint8_t capacity;
47+
uint8_t head;
48+
uint8_t tail;
49+
uint8_t count;
50+
uint8_t strlen;
51+
} log_data = {
52+
{ "", "", "", "", "", "", "", "", "", "" },
53+
LOG_LINES_COUNT,
54+
0,
55+
0,
56+
0,
57+
LOG_LINES_MAX_LEN
58+
};
5159

5260
static struct GuiEventMsgs {
5361
char **messages;
@@ -56,19 +64,6 @@ static struct GuiEventMsgs {
5664
unsigned int strlen;
5765
} event_messages = DEFAULT_EVENT_MESSAGES;
5866

59-
static void
60-
gui_malloc_log(void)
61-
{
62-
if (log_data.log != NULL)
63-
return;
64-
65-
unsigned int i;
66-
67-
log_data.log = ec_malloc(log_data.len * sizeof(char*));
68-
for (i = 0; i < log_data.len; ++i)
69-
log_data.log[i] = NULL;
70-
}
71-
7267
static void
7368
gui_malloc_eventmessages(void)
7469
{
@@ -273,7 +268,6 @@ gui_create(Camera *cam)
273268
POS_Y_COLLECTABLES + 32 + 5
274269
));
275270

276-
gui_malloc_log();
277271
gui_malloc_eventmessages();
278272

279273
init_sprites(gui, cam);
@@ -599,31 +593,32 @@ gui_reset(Gui *gui, Camera *cam)
599593
void
600594
gui_log(const char *fmt, ...)
601595
{
602-
char buffer[200];
603-
char *new_message;
596+
char buffer[LOG_LINES_MAX_LEN];
597+
uint8_t next_idx;
598+
char *next_message;
604599
char tstamp[10];
605600

606601
va_list args;
607602

608-
new_message = ec_malloc(log_data.strlen * sizeof(char));
609-
timestamp(tstamp, 10);
603+
next_idx = (uint8_t)(log_data.head + 1) % log_data.capacity;
604+
605+
// Increment indexes
606+
if (log_data.count > 0 && log_data.head == log_data.tail) {
607+
log_data.tail = (uint8_t)(log_data.tail + 1) % log_data.capacity;
608+
log_data.count = log_data.capacity;
609+
} else if (log_data.count < log_data.capacity) {
610+
log_data.count++;
611+
}
612+
613+
next_message = log_data.log[log_data.head];
614+
log_data.head = next_idx;
610615

616+
// Build log line
617+
timestamp(tstamp, 10);
611618
va_start(args, fmt);
612-
m_vsprintf(buffer, 200, fmt, args);
619+
m_vsprintf(buffer, LOG_LINES_MAX_LEN, fmt, args);
613620
va_end(args);
614-
m_sprintf(new_message, log_data.strlen, "%s > %s", tstamp, buffer);
615-
616-
log_data.count++;
617-
if (log_data.count > log_data.len) {
618-
log_data.count = log_data.len;
619-
free(log_data.log[0]);
620-
log_data.log[0] = NULL;
621-
for (size_t i = 0; i < log_data.count - 1; ++i) {
622-
log_data.log[i] = log_data.log[i+1];
623-
log_data.log[i+1] = NULL;
624-
}
625-
}
626-
log_data.log[log_data.count-1] = new_message;
621+
m_sprintf(next_message, log_data.strlen, "%s > %s", tstamp, buffer);
627622
}
628623

629624
void
@@ -656,15 +651,27 @@ gui_render_tooltip(Gui *gui, Camera *cam)
656651
void
657652
gui_render_log(Gui *gui, Camera *cam)
658653
{
659-
SDL_Rect box = { 16, 0, 16, 16 };
654+
static uint8_t last_head = 0;
660655

661656
sprite_render(gui->bottomFrame, cam);
662657

663-
for (Uint32 i = 0; i < log_data.count; ++i) {
658+
// Update log textures
659+
const uint8_t visible = log_data.count;
660+
if (log_data.head != last_head) {
661+
for (uint8_t i = 0; i < visible; ++i) {
662+
const uint8_t log_index = (uint8_t)((log_data.tail + i) % log_data.capacity);
663+
Texture *t = gui->log_lines[i];
664+
texture_load_from_text(t, log_data.log[log_index], C_WHITE, C_BLACK, cam->renderer);
665+
}
666+
}
667+
last_head = log_data.head;
668+
669+
// Render log textures
670+
SDL_Rect box = { 16, 0, 16, 16 };
671+
for (uint8_t i = 0; i < visible; ++i) {
664672
Texture *t;
665673
box.y = 16 + ((LOG_FONT_SIZE+5) * i);
666674
t = gui->log_lines[i];
667-
texture_load_from_text(t, log_data.log[i], C_WHITE, C_BLACK, cam->renderer);
668675
box.w = t->dim.width;
669676
box.h = t->dim.height;
670677
texture_render(t, &box, cam);
@@ -714,25 +721,12 @@ gui_clear_message_log(void)
714721
}
715722
event_messages.count = 0;
716723

717-
for (size_t i = 0; i < log_data.count; ++i)
718-
free(log_data.log[i]);
724+
// Don't need to clear the log buffer. Just reset the head/tail
725+
log_data.head = 0;
726+
log_data.tail = 0;
719727
log_data.count = 0;
720728
}
721729

722-
static void
723-
destroy_log(void)
724-
{
725-
if (log_data.log == NULL)
726-
return;
727-
728-
unsigned int i;
729-
for (i = 0; i < log_data.count; ++i)
730-
free(log_data.log[i]);
731-
732-
free(log_data.log);
733-
log_data.log = NULL;
734-
}
735-
736730
static void
737731
destroy_event_messages(void)
738732
{
@@ -750,7 +744,6 @@ destroy_event_messages(void)
750744
void
751745
gui_destroy(Gui *gui)
752746
{
753-
destroy_log();
754747
destroy_event_messages();
755748

756749
timer_destroy(gui->event_message_timer);

src/gui.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "roommatrix.h"
2323
#define LOG_LINES_COUNT 10
24+
#define LOG_LINES_MAX_LEN 200
2425
#define LOG_FONT_SIZE 8
2526
#define LABEL_FONT_SIZE 8
2627

src/main.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,15 +1013,29 @@ run_game_update(void)
10131013
static void
10141014
render_gui(void)
10151015
{
1016+
TIME_FUNC_BEGIN();
1017+
TIME_BLOCK_BEGIN(gui_render_panel);
10161018
SDL_SetRenderViewport(gRenderer, &statsGuiViewport);
10171019
gui_render_panel(gGui, gCamera);
1020+
TIME_BLOCK_END(gui_render_panel);
1021+
1022+
TIME_BLOCK_BEGIN(render_minimap);
10181023
SDL_SetRenderViewport(gRenderer, &minimapViewport);
10191024
gui_render_minimap(gGui, gCamera);
1025+
TIME_BLOCK_END(render_minimap);
1026+
1027+
TIME_BLOCK_BEGIN(render_skillbar);
10201028
SDL_SetRenderViewport(gRenderer, &skillBarViewport);
10211029
skillbar_render(gSkillBar, gPlayer, gCamera);
1030+
TIME_BLOCK_END(render_skillbar);
1031+
1032+
TIME_BLOCK_BEGIN(render_log);
10221033
SDL_SetRenderViewport(gRenderer, &bottomGuiViewport);
10231034
gui_render_log(gGui, gCamera);
1035+
TIME_BLOCK_END(render_log);
1036+
10241037
SDL_SetRenderViewport(gRenderer, &mainViewport);
1038+
TIME_FUNC_END();
10251039
}
10261040

10271041
static void

0 commit comments

Comments
 (0)