ref: 546fc01da819c76655da407b74699f8c77da998b
parent: da71b1fbb21ab3a4a7d0629f5c597ee03eff6227
author: Jonne Kokkonen <jonne.kokkonen@gmail.com>
date: Thu Apr 24 05:10:07 EDT 2025
Better scaling for fullscreen, deprecate devcontainer Use a 2 pass scaling with an intermediate texture when integer scaling is turned off to get better quality
--- a/.devcontainer.json
+++ /dev/null
@@ -1,5 +1,0 @@
-{- "build": {- "dockerfile": "Dockerfile"
- }
-}
\ No newline at end of file
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,9 +4,16 @@
set(APP_NAME m8c)
-option(USE_LIBSERIALPORT "Use libserialport as a backend" ON)
+option(USE_LIBSERIALPORT "Use libserialport as a backend" OFF)
option(USE_LIBUSB "Use libusb as a backend" OFF)
option(USE_RTMIDI "Use RtMidi as a backend" OFF)
+
+# Enable USE_LIBSERIALPORT by default if neither USE_LIBUSB nor USE_RTMIDI are defined
+if (NOT USE_LIBUSB AND NOT USE_RTMIDI)
+ message(STATUS "Neither USE_LIBUSB nor USE_RTMIDI are enabled. Enabling USE_LIBSERIALPORT by default.")
+ set(USE_LIBSERIALPORT ON)
+endif ()
+
file(GLOB m8c_SRC "src/*.h" "src/*.c" "src/backends/*.h" "src/backends/*.c" "src/fonts/*.h")
--- a/Dockerfile
+++ /dev/null
@@ -1,2 +1,0 @@
-FROM mcr.microsoft.com/devcontainers/cpp
-RUN apt-get update && apt-get install -y libsdl2-dev libserialport-dev
--- a/src/events.c
+++ b/src/events.c
@@ -18,6 +18,13 @@
case SDL_EVENT_TERMINATING:
ret_val = SDL_APP_SUCCESS;
break;
+ case SDL_EVENT_WINDOW_RESIZED:
+ case SDL_EVENT_WINDOW_MOVED:
+ // If the window size is changed, some operating systems might need a little nudge to fix scaling
+ renderer_fix_texture_scaling_after_window_resize(&ctx->conf);
+ break;
+
+ // --- iOS specific events ---
case SDL_EVENT_DID_ENTER_BACKGROUND:
// iOS: Application entered into the background on iOS. About 5 seconds to stop things.
SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Received SDL_EVENT_DID_ENTER_BACKGROUND");
@@ -40,11 +47,8 @@
renderer_clear_screen();
m8_resume_processing();
}
- case SDL_EVENT_WINDOW_RESIZED:
- case SDL_EVENT_WINDOW_MOVED:
- // If the window size is changed, some operating systems might need a little nudge to fix scaling
- renderer_fix_texture_scaling_after_window_resize();
- break;
+ case SDL_EVENT_FINGER_DOWN:
+
// --- Input events ---
case SDL_EVENT_GAMEPAD_ADDED:
--- a/src/input.h
+++ b/src/input.h
@@ -51,5 +51,6 @@
void input_handle_key_up_event(const struct app_context *ctx, const SDL_Event *event);
void input_handle_gamepad_button(struct app_context *ctx, SDL_GamepadButton button, bool pressed);
void input_handle_gamepad_axis(const struct app_context *ctx, SDL_GamepadAxis axis, Sint16 value);
+void input_handle_finger_down(const struct app_context *ctx, const SDL_Event *event);
#endif // INPUT_H
--- a/src/main.c
+++ b/src/main.c
@@ -31,7 +31,7 @@
screensaver_initialized = screensaver_init();
}
screensaver_draw();
- render_screen();
+ render_screen(&ctx->conf);
// Poll for M8 device every second
if (ctx->device_connected == 0 && SDL_GetTicks() - ticks_poll_device > 1000) {@@ -45,14 +45,14 @@
}
}
- const int m8_enabled = m8_enable_display(0);
+ const int m8_enabled = m8_enable_display(1);
// Device was found; enable display and proceed to the main loop
if (m8_enabled == 1) {ctx->app_state = RUN;
ctx->device_connected = 1;
+ SDL_Delay(100); // Give the display time to initialize
screensaver_destroy();
screensaver_initialized = 0;
- SDL_Delay(100); // Give the device time to initialize
m8_reset_display(); // Avoid display glitches.
} else {SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "Device not detected.");
@@ -87,10 +87,13 @@
}
config_params_s conf = config_initialize(*config_filename);
-#ifndef TARGET_OS_IOS
- // It's not possible to edit the config on iOS, so let's go with the defaults
- config_read(&conf);
-#endif
+ if (TARGET_OS_IOS == 0) {+ // It's not possible to edit the config on iOS, so let's go with the defaults
+ config_read(&conf);
+ } else {+ // Use integer scaling on iOS
+ conf.integer_scaling = 0;
+ }
return conf;
}
@@ -141,7 +144,7 @@
} else if (result == DEVICE_FATAL_ERROR) {return SDL_APP_FAILURE;
}
- render_screen();
+ render_screen(&ctx->conf);
break;
}
@@ -168,7 +171,6 @@
*appstate = ctx;
ctx->app_state = INITIALIZE;
-
ctx->conf = initialize_config(argc, argv, &ctx->preferred_device, &config_filename);
ctx->device_connected =
handle_m8_connection_init(ctx->conf.wait_for_device, ctx->preferred_device);
@@ -192,13 +194,13 @@
return SDL_APP_FAILURE;
}
- if (ctx->device_connected && m8_enable_display(0)) {+ if (ctx->device_connected && m8_enable_display(1)) { if (ctx->conf.audio_enabled) {audio_initialize(ctx->conf.audio_device_name, ctx->conf.audio_buffer_size);
}
ctx->app_state = RUN;
- SDL_Delay(100); // Give the device time to initialize
- m8_reset_display(); // Avoid display glitches.
+ render_screen(&ctx->conf);
+ m8_reset_display(); // Second reset to avoid display glitches.
} else {SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "Device not detected.");
ctx->device_connected = 0;
--- a/src/render.c
+++ b/src/render.c
@@ -19,12 +19,13 @@
#include <stdlib.h>
-SDL_Window *win;
-SDL_Renderer *rend;
-SDL_Texture *main_texture;
-SDL_Color global_background_color = (SDL_Color){.r = 0x00, .g = 0x00, .b = 0x00, .a = 0x00};-SDL_RendererLogicalPresentation window_scaling_mode = SDL_LOGICAL_PRESENTATION_INTEGER_SCALE;
-SDL_ScaleMode texture_scaling_mode = SDL_SCALEMODE_NEAREST;
+static SDL_Window *win;
+static SDL_Renderer *rend;
+static SDL_Texture *main_texture;
+static SDL_Texture *hd_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;
static uint32_t ticks_fps;
static int fps;
@@ -44,79 +45,46 @@
uint8_t fullscreen = 0;
-static uint8_t dirty = 0;
+static uint8_t dirty = 1;
-static void use_integer_scaling(const unsigned int use_integer_scaling) {- if (use_integer_scaling) {- window_scaling_mode = SDL_LOGICAL_PRESENTATION_INTEGER_SCALE;
- texture_scaling_mode = SDL_SCALEMODE_NEAREST;
- } else {- window_scaling_mode = SDL_LOGICAL_PRESENTATION_LETTERBOX;
- texture_scaling_mode = SDL_SCALEMODE_NEAREST;
- }
- renderer_fix_texture_scaling_after_window_resize();
-}
+// Creates an intermediate texture dynamically based on window size
+static void create_hd_texture() {+ SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "Creating HD texture");
+ int window_width, window_height;
-// Initializes SDL and creates a renderer and required surfaces
-int renderer_initialize(config_params_s *conf) {+ // Get the current window size
+ SDL_GetWindowSize(win, &window_width, &window_height);
- // SDL documentation recommends this
- atexit(SDL_Quit);
-
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) == false) {- SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "SDL_Init: %s", SDL_GetError());
- return 0;
+ // Calculate the maximum integer scaling factor
+ int scale_factor = SDL_min(window_width / texture_width, window_height / texture_height);
+ if (scale_factor < 1) {+ scale_factor = 1; // Ensure at least 1x scaling
}
+ SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "HD texture scale factor: %d", scale_factor);
- if (!SDL_CreateWindowAndRenderer("m8c", texture_width * 2, texture_height * 2,- SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY |
- SDL_WINDOW_OPENGL | conf->init_fullscreen,
- &win, &rend)) {- SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window and renderer: %s",
- SDL_GetError());
- return false;
- }
+ // Calculate the HD texture size
+ const int hd_texture_width = texture_width * scale_factor;
+ const int hd_texture_height = texture_height * scale_factor;
+ SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "HD texture size: %dx%d", hd_texture_width,
+ hd_texture_height);
- SDL_SetRenderVSync(rend, 1);
-
- if (!SDL_SetRenderLogicalPresentation(rend, texture_width, texture_height, window_scaling_mode)) {- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set renderer logical presentation: %s",
- SDL_GetError());
- return false;
+ // Destroy any existing HD texture
+ if (hd_texture != NULL) {+ SDL_DestroyTexture(hd_texture);
}
- main_texture = NULL;
- main_texture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET,
- texture_width, texture_height);
-
- if (main_texture == NULL) {- SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s", SDL_GetError());
- return false;
+ // Create a new HD texture with the calculated size
+ hd_texture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET,
+ hd_texture_width, hd_texture_height);
+ if (!hd_texture) {+ SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't create HD texture: %s", SDL_GetError());
}
- SDL_SetTextureScaleMode(main_texture, texture_scaling_mode);
- use_integer_scaling(conf->integer_scaling);
-
- SDL_SetRenderTarget(rend, main_texture);
-
- SDL_SetRenderDrawColor(rend, global_background_color.r, global_background_color.g,
- global_background_color.b, global_background_color.a);
-
- if (!SDL_RenderClear(rend)) {- SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Couldn't clear renderer: %s", SDL_GetError());
- return 0;
+ // Optionally, set a linear scaling mode for smoother rendering
+ if (!SDL_SetTextureScaleMode(hd_texture, SDL_SCALEMODE_LINEAR)) {+ SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't set HD texture scale mode: %s",
+ SDL_GetError());
}
-
- renderer_set_font_mode(0);
-
- SDL_SetHint(SDL_HINT_IOS_HIDE_HOME_INDICATOR, "1");
-
- dirty = 1;
-
- SDL_PumpEvents();
- render_screen();
-
- return 1;
}
static void change_font(struct inline_font *font) {@@ -142,7 +110,15 @@
SDL_SetWindowSize(win, texture_width * 2, texture_height * 2);
}
- SDL_DestroyTexture(main_texture);
+ if (hd_texture != NULL) {+ SDL_DestroyTexture(hd_texture);
+ create_hd_texture(); // Create the texture dynamically based on window size
+ }
+
+ if (main_texture != NULL) {+ SDL_DestroyTexture(main_texture);
+ }
+
SDL_SetRenderLogicalPresentation(rend, texture_width, texture_height, window_scaling_mode);
main_texture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET,
texture_width, texture_height);
@@ -185,7 +161,12 @@
void renderer_close(void) {SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "Closing renderer");
inline_font_close();
- SDL_DestroyTexture(main_texture);
+ if (main_texture != NULL) {+ SDL_DestroyTexture(main_texture);
+ }
+ if (hd_texture != NULL) {+ SDL_DestroyTexture(hd_texture);
+ }
SDL_DestroyRenderer(rend);
SDL_DestroyWindow(win);
}
@@ -334,43 +315,187 @@
dirty = 1;
}
-void render_screen(void) {- if (dirty) {- dirty = 0;
+static void log_fps_stats(void) {+ fps++;
- if (!SDL_SetRenderTarget(rend, NULL)) {- SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't set renderer target to window: %s", SDL_GetError());
+ if (SDL_GetTicks() - ticks_fps > 5000) {+ ticks_fps = SDL_GetTicks();
+ SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "%.1f fps\n", (float)fps / 5);
+ fps = 0;
+ }
+}
+
+// Initializes SDL and creates a renderer and required surfaces
+int renderer_initialize(config_params_s *conf) {+
+ // SDL documentation recommends this
+ atexit(SDL_Quit);
+
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) == false) {+ SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "SDL_Init: %s", SDL_GetError());
+ return 0;
+ }
+
+ if (!SDL_CreateWindowAndRenderer("m8c", texture_width * 2, texture_height * 2,+ SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY |
+ SDL_WINDOW_OPENGL | conf->init_fullscreen,
+ &win, &rend)) {+ SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window and renderer: %s",
+ SDL_GetError());
+ return false;
+ }
+
+ SDL_SetRenderVSync(rend, 1);
+
+ if (!SDL_SetRenderLogicalPresentation(rend, texture_width, texture_height, window_scaling_mode)) {+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set renderer logical presentation: %s",
+ SDL_GetError());
+ return false;
+ }
+
+ main_texture = NULL;
+ main_texture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET,
+ texture_width, texture_height);
+
+ if (main_texture == NULL) {+ SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s", SDL_GetError());
+ return false;
+ }
+
+ SDL_SetTextureScaleMode(main_texture, texture_scaling_mode);
+
+ SDL_SetRenderTarget(rend, main_texture);
+
+ SDL_SetRenderDrawColor(rend, global_background_color.r, global_background_color.g,
+ global_background_color.b, global_background_color.a);
+
+ if (!SDL_RenderClear(rend)) {+ SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Couldn't clear renderer: %s", SDL_GetError());
+ return 0;
+ }
+
+ renderer_set_font_mode(0);
+
+ SDL_SetHint(SDL_HINT_IOS_HIDE_HOME_INDICATOR, "1");
+
+ dirty = 1;
+
+ SDL_PumpEvents();
+ render_screen(conf);
+
+ return 1;
+}
+
+void render_screen(config_params_s *conf) {+ if (!dirty) {+ // No draw commands have been issued since the last function call, do nothing
+ return;
+ }
+
+ if (!conf) {+ SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "render_screen configuration parameter is NULL.");
+ return;
+ }
+
+ dirty = 0;
+
+ if (!SDL_SetRenderTarget(rend, NULL)) {+ SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't set renderer target to window: %s",
+ SDL_GetError());
+ }
+
+ if (!SDL_SetRenderDrawColor(rend, global_background_color.r, global_background_color.g,
+ global_background_color.b, global_background_color.a)) {+ SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't set render draw color: %s", SDL_GetError());
+ }
+
+ if (!SDL_RenderClear(rend)) {+ SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't clear renderer: %s", SDL_GetError());
+ }
+
+ if (conf->integer_scaling) {+ // Direct rendering with integer scaling
+ if (!SDL_RenderTexture(rend, main_texture, NULL, NULL)) {+ SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't render texture: %s", SDL_GetError());
}
+ } else {- if (!SDL_SetRenderDrawColor(rend, global_background_color.r, global_background_color.g,
- global_background_color.b, global_background_color.a)) {- SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't set render draw color: %s", SDL_GetError());
+ int window_width, window_height;
+ if (!SDL_GetWindowSize(win, &window_width, &window_height)) {+ SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't get window size: %s", SDL_GetError());
}
- if (!SDL_RenderClear(rend)) {- SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't clear renderer: %s", SDL_GetError());
+ // Determine the texture aspect ratio
+ const float texture_aspect_ratio = (float)texture_width / (float)texture_height;
+
+ // Determine the window aspect ratio
+ const float window_aspect_ratio = (float)window_width / (float)window_height;
+
+ // Ensure that HD texture exists
+ if (hd_texture == NULL) {+ create_hd_texture(); // Create the texture dynamically based on window size
}
- if (!SDL_RenderTexture(rend, main_texture, NULL, NULL)) {- SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't render texture: %s", SDL_GetError());
+ if (!SDL_SetRenderTarget(rend, hd_texture)) {+ SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't set HD render target: %s", SDL_GetError());
}
- if (!SDL_RenderPresent(rend)) {- SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't present renderer: %s", SDL_GetError());
+ // Fill HD texture with BG color
+ SDL_SetRenderDrawColor(rend, global_background_color.r, global_background_color.g,
+ global_background_color.b, global_background_color.a);
+
+ if (!SDL_RenderClear(rend)) {+ SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't clear HD texture: %s", SDL_GetError());
}
- if (!SDL_SetRenderTarget(rend, main_texture)) {- SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't set renderer target to texture: %s", SDL_GetError());
+ // Render the main texture to hd_texture. It has the same aspect ratio, so a NULL rect works.
+ if (!SDL_RenderTexture(rend, main_texture, NULL, NULL)) {+ SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't render main texture to HD texture: %s",
+ SDL_GetError());
+ };
+
+ // Switch the render target back to the window
+ if (!SDL_SetRenderTarget(rend, NULL)) {+ SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't reset render target to window: %s",
+ SDL_GetError());
}
- fps++;
+ float texture_width_hd, texture_height_hd;
+ SDL_GetTextureSize(hd_texture, &texture_width_hd, &texture_height_hd);
- if (SDL_GetTicks() - ticks_fps > 5000) {- ticks_fps = SDL_GetTicks();
- SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "%.1f fps\n", (float)fps / 5);
- fps = 0;
+ SDL_FRect dest_rect;
+
+ if (window_aspect_ratio > texture_aspect_ratio) {+ // Window is relatively wider than the texture
+ dest_rect.h = (float)window_height;
+ dest_rect.w = dest_rect.h * texture_aspect_ratio;
+ dest_rect.x = ((float)window_width - dest_rect.w) / 2.0f;
+ dest_rect.y = 0;
+ SDL_RenderTexture(rend, hd_texture, NULL, &dest_rect);
+ } else if (window_aspect_ratio < texture_aspect_ratio) {+ // Window is relatively taller than the texture
+ dest_rect.w = (float)window_width;
+ dest_rect.h = dest_rect.w / texture_aspect_ratio;
+ dest_rect.x = 0;
+ dest_rect.y = ((float)window_height - dest_rect.h) / 2.0f;
+ // Render the HD texture with the calculated destination rectangle
+ SDL_RenderTexture(rend, hd_texture, NULL, &dest_rect);
+ } else {+ // Window and texture aspect ratios match
+ SDL_RenderTexture(rend, hd_texture, NULL, NULL);
}
}
+
+ if (!SDL_RenderPresent(rend)) {+ SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't present renderer: %s", SDL_GetError());
+ }
+
+ if (!SDL_SetRenderTarget(rend, main_texture)) {+ SDL_LogCritical(SDL_LOG_CATEGORY_RENDER, "Couldn't set renderer target to texture: %s",
+ SDL_GetError());
+ }
+
+ log_fps_stats();
}
int screensaver_init(void) {@@ -377,7 +502,7 @@
if (screensaver_initialized) {return 1;
}
- SDL_SetRenderTarget(rend,main_texture);
+ SDL_SetRenderTarget(rend, main_texture);
renderer_set_font_mode(1);
global_background_color.r = 0, global_background_color.g = 0, global_background_color.b = 0;
fx_cube_init(rend, (SDL_Color){255, 255, 255, 255}, texture_width, texture_height,@@ -396,9 +521,23 @@
screensaver_initialized = 0;
}
-void renderer_fix_texture_scaling_after_window_resize(void) {+void renderer_fix_texture_scaling_after_window_resize(config_params_s *conf) {SDL_SetRenderTarget(rend, NULL);
- SDL_SetRenderLogicalPresentation(rend, texture_width, texture_height, window_scaling_mode);
+ if (conf->integer_scaling) {+ // SDL internal integer scaling works well for this purpose
+ SDL_SetRenderLogicalPresentation(rend, texture_width, texture_height,
+ SDL_LOGICAL_PRESENTATION_INTEGER_SCALE);
+ } else {+ // Fullscreen scaling: use an intermediate texture with the highest possible integer size factor
+ if (hd_texture != NULL) {+ SDL_DestroyTexture(hd_texture);
+ create_hd_texture();
+ }
+ // SDL forces black borders in letterbox mode, so in HD mode the texture scaling is manual
+ SDL_SetRenderLogicalPresentation(rend, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED);
+ SDL_SetTextureScaleMode(main_texture, SDL_SCALEMODE_NEAREST);
+ SDL_SetTextureScaleMode(hd_texture, SDL_SCALEMODE_LINEAR);
+ }
SDL_SetTextureScaleMode(main_texture, texture_scaling_mode);
}
--- a/src/render.h
+++ b/src/render.h
@@ -12,7 +12,7 @@
int renderer_initialize(config_params_s *conf);
void renderer_close(void);
void renderer_set_font_mode(int mode);
-void renderer_fix_texture_scaling_after_window_resize(void);
+void renderer_fix_texture_scaling_after_window_resize(config_params_s *conf);
void renderer_clear_screen(void);
void draw_waveform(struct draw_oscilloscope_waveform_command *command);
@@ -21,7 +21,7 @@
void set_m8_model(unsigned int model);
-void render_screen(void);
+void render_screen(config_params_s *conf);
void toggle_fullscreen(void);
void display_keyjazz_overlay(uint8_t show, uint8_t base_octave, uint8_t velocity);
--
⑨