ref: e11f4056d9188a2124a8dfb4dc2f95b5f196963c
parent: 6aa48d6e0f993dd4adc35aaa5a41b220e0652cc7
author: laamaa <jonne.kokkonen@gmail.com>
date: Wed Sep 10 04:42:50 EDT 2025
modularize log overlay system, move implementations to dedicated file and simplify render path integration
--- a/src/common.h
+++ b/src/common.h
@@ -2,6 +2,12 @@
#define COMMON_H_
#include "config.h"
+// On MacOS TARGET_OS_IOS is defined as 0, so make sure that it's consistent on other platforms as
+// well
+#ifndef TARGET_OS_IOS
+#define TARGET_OS_IOS 0
+#endif
+
enum app_state { QUIT, INITIALIZE, WAIT_FOR_DEVICE, RUN }; struct app_context {--- a/src/input.c
+++ b/src/input.c
@@ -6,6 +6,7 @@
#include "backends/m8.h"
#include "common.h"
#include "render.h"
+#include "log_overlay.h"
#include <SDL3/SDL.h>
static unsigned char keyjazz_enabled = 0;
@@ -184,13 +185,15 @@
return;
}
if (event->key.key == SDLK_ESCAPE) {- display_keyjazz_overlay(toggle_input_keyjazz(), keyjazz_base_octave, keyjazz_velocity);
+ if (ctx->app_state == RUN) {+ display_keyjazz_overlay(toggle_input_keyjazz(), keyjazz_base_octave, keyjazz_velocity);
+ }
return;
}
// Toggle in-app log overlay using config-defined key
if (event->key.scancode == ctx->conf.key_toggle_log) {- renderer_toggle_log_overlay();
+ log_overlay_toggle();
return;
}
--- a/src/main.c
+++ b/src/main.c
@@ -19,13 +19,8 @@
#include "config.h"
#include "gamepads.h"
#include "render.h"
+#include "log_overlay.h"
-// On MacOS TARGET_OS_IOS is defined as 0, so make sure that it's consistent on other platforms as
-// well
-#ifndef TARGET_OS_IOS
-#define TARGET_OS_IOS 0
-#endif
-
static void do_wait_for_device(struct app_context *ctx) {static Uint64 ticks_poll_device = 0;
static int screensaver_initialized = 0;
@@ -151,7 +146,7 @@
char *config_filename = NULL;
// Initialize in-app log capture/overlay
- renderer_log_init();
+ log_overlay_init();
#ifndef NDEBUG
// Show debug messages in the application log
--- a/src/render.c
+++ b/src/render.c
@@ -9,6 +9,7 @@
#include "command.h"
#include "config.h"
#include "fx_cube.h"
+#include "log_overlay.h"
#include "settings.h"
#include "fonts/fonts.h"
@@ -19,7 +20,6 @@
static SDL_Renderer *rend;
static SDL_Texture *main_texture;
static SDL_Texture *hd_texture = NULL;
-static SDL_Texture *log_texture = NULL;
static SDL_Color global_background_color = (SDL_Color){.r = 0x00, .g = 0x00, .b = 0x00, .a = 0x00};static SDL_RendererLogicalPresentation window_scaling_mode = SDL_LOGICAL_PRESENTATION_INTEGER_SCALE;
static SDL_ScaleMode texture_scaling_mode = SDL_SCALEMODE_NEAREST;
@@ -32,21 +32,8 @@
static int text_offset_y = 0;
static int waveform_max_height = 24;
-// Log overlay state
-static int log_overlay_visible = 0;
-static int log_overlay_needs_redraw = 0;
+// Log overlay moved to log_overlay.c
-// Log buffer configuration
-#define LOG_BUFFER_MAX_LINES 512
-#define LOG_LINE_MAX_CHARS 256
-static char log_lines[LOG_BUFFER_MAX_LINES][LOG_LINE_MAX_CHARS];
-static int log_line_start = 0; // index of the oldest line
-static int log_line_count = 0; // number of valid lines
-
-// Previous SDL log output forwarding
-static SDL_LogOutputFunction prev_log_output_fn = NULL;
-static void *prev_log_output_userdata = NULL;
-
static int texture_width = 320;
static int texture_height = 240;
static int hd_texture_width, hd_texture_height = 0;
@@ -144,163 +131,14 @@
inline_font_initialize(fonts_get(index));
}
-// Append a formatted line to the circular log buffer
-static void log_buffer_append_line(const char *line) {- if (line[0] == '\0') {- return;
- }
- const int index = (log_line_start + log_line_count) % LOG_BUFFER_MAX_LINES;
- SDL_strlcpy(log_lines[index], line, LOG_LINE_MAX_CHARS);
- if (log_line_count < LOG_BUFFER_MAX_LINES) {- log_line_count++;
- } else {- log_line_start = (log_line_start + 1) % LOG_BUFFER_MAX_LINES;
- }
- log_overlay_needs_redraw = 1;
-}
+// Log overlay API wrappers
+void renderer_log_init(void) { log_overlay_init(); }-// SDL log output function that mirrors to our in-app buffer in addition to the default handler
-static void sdl_log_capture(void *userdata, int category, SDL_LogPriority priority,
- const char *message) {- (void)userdata;
- (void)category;
- (void)priority;
-
- char formatted[LOG_LINE_MAX_CHARS];
- SDL_snprintf(formatted, sizeof(formatted), ">%s", message ? message : "");
-
- // Copy the formatted message into our buffer
- log_buffer_append_line(formatted);
-
- // Forward to the previous output function so messages still hit the console
- if (prev_log_output_fn != NULL) {- prev_log_output_fn(prev_log_output_userdata, category, priority, message);
- }
-}
-
-void renderer_log_init(void) {- // Preserve the existing output function and install our capture wrapper
- SDL_GetLogOutputFunction(&prev_log_output_fn, &prev_log_output_userdata);
- SDL_SetLogOutputFunction(sdl_log_capture, NULL);
-}
-
void renderer_toggle_log_overlay(void) {- log_overlay_visible = !log_overlay_visible;
- // Force redraw next present
+ log_overlay_toggle();
dirty = 1;
- log_overlay_needs_redraw = 1;
}
-// Render the log buffer into a texture for the overlay display
-static void render_log_overlay_texture(void) {- if (!log_overlay_visible) {- return;
- }
- if (log_texture == NULL) {- log_texture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET,
- texture_width, texture_height);
- if (log_texture == NULL) {- SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Couldn't create log texture: %s", SDL_GetError());
- return;
- }
- // Ensure overlay blends and scales consistently with the main texture
- SDL_SetTextureBlendMode(log_texture, SDL_BLENDMODE_BLEND);
- SDL_SetTextureScaleMode(log_texture, texture_scaling_mode);
- }
-
- if (!log_overlay_needs_redraw) {- return;
- }
- log_overlay_needs_redraw = 0;
-
- SDL_Texture *prev_target = SDL_GetRenderTarget(rend);
- SDL_SetRenderTarget(rend, log_texture);
-
- // Semi-transparent background rectangle
- SDL_SetRenderDrawColor(rend, 0, 0, 0, 220);
- SDL_RenderClear(rend);
-
- // Use a small font to fit more lines
- const int prev_font_mode = font_mode;
- inline_font_close();
- const struct inline_font *font_small = fonts_get(0);
- inline_font_initialize(font_small);
-
- const int line_height = font_small->glyph_y + 1;
- const int margin_x = 2;
- const int margin_y = 1;
- const int usable_width = texture_width - (margin_x * 2);
- const int cols = SDL_max(1, usable_width / (font_small->glyph_x + 1));
-
- // Compute how many text rows fit
- const int max_rows = (texture_height - margin_y * 2) / line_height;
- int rows_needed = max_rows;
-
- // Determine start line and character offset so the overlay shows the most recent rows
- const int newest_idx =
- (log_line_start + log_line_count - 1 + LOG_BUFFER_MAX_LINES) % LOG_BUFFER_MAX_LINES;
- int start_idx = log_line_start;
- size_t start_char_offset = 0;
-
- if (log_line_count > 0) {- for (int n = 0; n < log_line_count && rows_needed > 0; n++) {- const int idx = (newest_idx - n + LOG_BUFFER_MAX_LINES) % LOG_BUFFER_MAX_LINES;
- const size_t len = SDL_strlen(log_lines[idx]);
- const int rows_for_line = SDL_max(1, (int)((len + cols - 1) / cols));
- if (rows_for_line >= rows_needed) {- int offset = (int)len - rows_needed * cols;
- if (offset < 0) {- offset = 0;
- }
- start_idx = idx;
- start_char_offset = (size_t)offset;
- break;
- }
- rows_needed -= rows_for_line;
- start_idx = idx;
- start_char_offset = 0;
- }
- }
-
- // Render forward from the computed start to the newest
- if (log_line_count > 0) {- int y = 1;
- int cur = start_idx;
- const int last = newest_idx;
- size_t offset = start_char_offset;
- while (1) {- const char *s = log_lines[cur];
- const size_t len = SDL_strlen(s);
- for (size_t pos = offset; pos < len && y < texture_height;) {- const Uint32 bg = 0xFFFFFF;
- const Uint32 fg = 0xFFFFFF;
- const size_t remaining = len - pos;
- size_t take = (size_t)cols < remaining ? (size_t)cols : remaining;
- char buf[LOG_LINE_MAX_CHARS];
- if (take >= sizeof(buf)) {- take = sizeof(buf) - 1;
- }
- SDL_memcpy(buf, s + pos, take);
- buf[take] = '\0';
- inprint(rend, buf, margin_x, y, fg, bg);
- y += line_height;
- pos += take;
- }
- if (cur == last || y >= texture_height) {- break;
- }
- cur = (cur + 1) % LOG_BUFFER_MAX_LINES;
- offset = 0;
- }
- }
-
- // Restore previous font
- inline_font_close();
- inline_font_initialize(fonts_get(prev_font_mode));
-
- SDL_SetRenderTarget(rend, prev_target);
-}
-
static void check_and_adjust_window_and_texture_size(const int new_width, const int new_height) { if (texture_width == new_width && texture_height == new_height) {@@ -328,11 +166,8 @@
SDL_DestroyTexture(main_texture);
}
- // Drop log texture so it can be recreated with the correct size
- if (log_texture != NULL) {- SDL_DestroyTexture(log_texture);
- log_texture = NULL;
- }
+ // Notify log overlay to drop its cached texture so it can be recreated with the new size
+ log_overlay_invalidate();
main_texture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET,
texture_width, texture_height);
@@ -385,9 +220,7 @@
if (hd_texture != NULL) {SDL_DestroyTexture(hd_texture);
}
- if (log_texture != NULL) {- SDL_DestroyTexture(log_texture);
- }
+ log_overlay_destroy();
SDL_DestroyRenderer(rend);
SDL_DestroyWindow(win);
}
@@ -644,16 +477,8 @@
if (conf->integer_scaling) {SDL_SetRenderTarget(rend, main_texture);
- // Ensure the log overlay is up to date, then composite it if visible before present
- if (log_overlay_visible) {- render_log_overlay_texture();
- if (log_texture) {- if (!SDL_RenderTexture(rend, log_texture, NULL, NULL)) {- SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't render log overlay texture to HD texture: %s",
- SDL_GetError());
- }
- }
- }
+ // Render log overlay (composites if visible)
+ log_overlay_render(rend, texture_width, texture_height, texture_scaling_mode, font_mode);
// Settings overlay composited last
if (settings_is_open()) {@@ -701,16 +526,8 @@
SDL_GetError());
}
- // Ensure the log overlay is up to date, then composite it if visible before present
- if (log_overlay_visible) {- render_log_overlay_texture();
- if (log_texture) {- if (!SDL_RenderTexture(rend, log_texture, NULL, NULL)) {- SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't render log overlay texture to HD texture: %s",
- SDL_GetError());
- }
- }
- }
+ // Render log overlay (composites if visible)
+ log_overlay_render(rend, texture_width, texture_height, texture_scaling_mode, font_mode);
// Settings overlay composited last
if (settings_is_open()) {--- a/src/render.h
+++ b/src/render.h
@@ -27,10 +27,6 @@
void show_error_message(const char *message);
-// Log overlay controls
-void renderer_log_init(void);
-void renderer_toggle_log_overlay(void);
-
int screensaver_init(void);
void screensaver_draw(void);
void screensaver_destroy(void);
--
⑨