From 9d629509bbcefe4782000da4f05704a724d236a7 Mon Sep 17 00:00:00 2001 From: Piotr Usewicz Date: Mon, 6 Jul 2026 19:14:42 +0200 Subject: [PATCH 1/6] Apply MSAA changes to pinned canvases cf_app_set_msaa() recreated the default canvas via cf_app_recreate_default_canvas_if_needed(), which no-ops once the canvas is pinned via cf_app_set_canvas_size(). That left app->sample_count updated but the actual canvas untouched, so MSAA changes silently had no effect for pinned-canvas apps even though the function reported success. Recreate the canvas directly at its current size instead, which respects pinning while still applying the new sample count. --- src/cute_app.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cute_app.cpp b/src/cute_app.cpp index e649c6d1..ec4ce5df 100644 --- a/src/cute_app.cpp +++ b/src/cute_app.cpp @@ -756,7 +756,7 @@ bool cf_app_set_msaa(int sample_count) if (supported && app->sample_count != sample_count) { app->sample_count = sample_count; - cf_app_recreate_default_canvas_if_needed(); + s_canvas(app->canvas_w, app->canvas_h); } return supported; From 0b561a3b8acae1a9df1b8eaf70f72793bc392048 Mon Sep 17 00:00:00 2001 From: Piotr Usewicz Date: Mon, 6 Jul 2026 19:14:53 +0200 Subject: [PATCH 2/6] Respect NO_HIGH_DPI_BIT in pixel scale refresh s_refresh_pixel_scale() unconditionally overwrote app->pixel_scale from SDL_GetWindowPixelDensity() on display/pixel-size change events, even when the app was created with CF_APP_OPTIONS_NO_HIGH_DPI_BIT. That contradicted cf_app_get_pixel_scale()'s documented guarantee to always return 1.0f when HiDPI is opted out, and could unexpectedly recreate the default canvas on a display change. Skip the refresh entirely when the flag is set. --- src/cute_input.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cute_input.cpp b/src/cute_input.cpp index 31c86d3f..7879d655 100644 --- a/src/cute_input.cpp +++ b/src/cute_input.cpp @@ -508,6 +508,7 @@ void cf_begin_frame_input() // both are handled the same way and this is idempotent when both fire together. static void s_refresh_pixel_scale() { + if (app->options & CF_APP_OPTIONS_NO_HIGH_DPI_BIT) return; float pixel_scale = SDL_GetWindowPixelDensity(app->window); if (pixel_scale <= 0.0f) pixel_scale = 1.0f; if (pixel_scale != app->pixel_scale) { From b1283206d48e634adeb3b48eb97863b192b9786d Mon Sep 17 00:00:00 2001 From: Piotr Usewicz Date: Mon, 6 Jul 2026 19:15:07 +0200 Subject: [PATCH 3/6] Cross-reference pixel_scale from window-size docs cf_app_get_size, cf_app_get_width, and cf_app_get_height all point readers to cf_app_get_pixel_scale for converting logical points to physical pixels, but none listed it in @related, making it harder to navigate to. Add it to all three for consistency. --- include/cute_app.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/cute_app.h b/include/cute_app.h index c6c10827..34f3de61 100644 --- a/include/cute_app.h +++ b/include/cute_app.h @@ -369,7 +369,7 @@ CF_API int CF_CALL cf_app_draw_onto_screen(bool clear); * @brief Gets the size of the window in logical points (called "points" on Retina/HiDPI displays; use `cf_app_get_pixel_scale` to convert to physical pixels). * @param w The width of the window in logical points. * @param h The height of the window in logical points. - * @related cf_app_set_size cf_app_get_position cf_app_set_position cf_app_get_width cf_app_get_height cf_app_get_dpi_scale + * @related cf_app_set_size cf_app_get_position cf_app_set_position cf_app_get_width cf_app_get_height cf_app_get_dpi_scale cf_app_get_pixel_scale */ CF_API void CF_CALL cf_app_get_size(int* w, int* h); @@ -377,7 +377,7 @@ CF_API void CF_CALL cf_app_get_size(int* w, int* h); * @function cf_app_get_width * @category app * @brief Returns the size of the window width in logical points (use `cf_app_get_pixel_scale` to convert to physical pixels). - * @related cf_app_set_size cf_app_get_position cf_app_set_position cf_app_get_width cf_app_get_height cf_app_get_dpi_scale + * @related cf_app_set_size cf_app_get_position cf_app_set_position cf_app_get_width cf_app_get_height cf_app_get_dpi_scale cf_app_get_pixel_scale */ CF_API int CF_CALL cf_app_get_width(void); @@ -385,7 +385,7 @@ CF_API int CF_CALL cf_app_get_width(void); * @function cf_app_get_height * @category app * @brief Returns the size of the window height in logical points (use `cf_app_get_pixel_scale` to convert to physical pixels). - * @related cf_app_set_size cf_app_get_position cf_app_set_position cf_app_get_width cf_app_get_height cf_app_get_dpi_scale + * @related cf_app_set_size cf_app_get_position cf_app_set_position cf_app_get_width cf_app_get_height cf_app_get_dpi_scale cf_app_get_pixel_scale */ CF_API int CF_CALL cf_app_get_height(void); From c32b875778ea18eb8ea64af2a815c124f9b2a596 Mon Sep 17 00:00:00 2001 From: Piotr Usewicz Date: Mon, 6 Jul 2026 19:15:19 +0200 Subject: [PATCH 4/6] Round physical canvas size in window_resizing sample (int)(window_w * pixel_scale) truncates for fractional pixel scales (common with Windows/Linux fractional display scaling), leaving the pinned canvas a pixel or more smaller than the actual swapchain and reintroducing the stretch blit the pinning was meant to avoid. Round instead, matching cf_app_recreate_default_canvas_if_needed()'s own use of CF_ROUNDF. --- samples/window_resizing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/window_resizing.cpp b/samples/window_resizing.cpp index 078a4bd6..09316c93 100644 --- a/samples/window_resizing.cpp +++ b/samples/window_resizing.cpp @@ -116,7 +116,7 @@ int main(int argc, char* argv[]) // blit is 1:1 and stays crisp on HiDPI displays. The projection below // stays in logical units, so game content doesn't move. float pixel_scale = app_get_pixel_scale(); - app_set_canvas_size((int)(window_w * pixel_scale), (int)(window_h * pixel_scale)); + app_set_canvas_size((int)CF_ROUNDF(window_w * pixel_scale), (int)CF_ROUNDF(window_h * pixel_scale)); CF_V2 dest = calculate_dest_size(game_w, game_h, window_w, window_h, scale_mode); // Draw the canvas scaled and centered in the window. From 234e94b4f7103200a34f20693142d6d2b5c3d21e Mon Sep 17 00:00:00 2001 From: Piotr Usewicz Date: Mon, 6 Jul 2026 19:58:04 +0200 Subject: [PATCH 5/6] Avoid stale canvas size on MSAA change cf_app_set_msaa() unconditionally recreated the canvas via s_canvas(app->canvas_w, app->canvas_h). For an unpinned canvas, app->canvas_w/h can be stale if cf_app_set_size() was just called -- it updates app->w/h immediately but only recreates the canvas on the next WINDOW_RESIZED event. Recreating from the stale canvas_w/h would briefly bake in the old size. Only use the fixed size when the canvas is pinned; otherwise call cf_app_recreate_default_canvas_if_needed() so it recomputes from the current app->w/h and pixel_scale. --- src/cute_app.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cute_app.cpp b/src/cute_app.cpp index ec4ce5df..77061a34 100644 --- a/src/cute_app.cpp +++ b/src/cute_app.cpp @@ -756,7 +756,11 @@ bool cf_app_set_msaa(int sample_count) if (supported && app->sample_count != sample_count) { app->sample_count = sample_count; - s_canvas(app->canvas_w, app->canvas_h); + if (app->canvas_pinned) { + s_canvas(app->canvas_w, app->canvas_h); + } else { + cf_app_recreate_default_canvas_if_needed(); + } } return supported; From ce3004f588edd7309b4769e0f346155484f3ecdd Mon Sep 17 00:00:00 2001 From: Piotr Usewicz Date: Mon, 6 Jul 2026 19:58:16 +0200 Subject: [PATCH 6/6] Document NO_HIGH_DPI_BIT no-op in pixel scale refresh The comment atop s_refresh_pixel_scale() described it as always updating pixel_scale/recreating the canvas, but didn't mention the early return added for CF_APP_OPTIONS_NO_HIGH_DPI_BIT, making the no-op behavior easy to miss when debugging pixel-scale issues in that mode. --- src/cute_input.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cute_input.cpp b/src/cute_input.cpp index 7879d655..7c927d4b 100644 --- a/src/cute_input.cpp +++ b/src/cute_input.cpp @@ -501,6 +501,8 @@ void cf_begin_frame_input() // Re-queries the window's physical pixel density and, if it changed, updates // app->pixel_scale and recreates the default canvas to match (unless pinned). +// No-ops entirely when CF_APP_OPTIONS_NO_HIGH_DPI_BIT is set, since pixel_scale +// must stay pinned at 1.0f in that mode. // Called from both SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED and // SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED -- the former is the OS's content-scale // signal and the latter is the authoritative physical-pixel-size signal;