enhancement: Highdpi aware renderer (#1472)

* feat: improve high-DPI rendering
Linux already works fine with scaling, but macOS works differently.

Let's see if this improves the situation

* TTF_SetFontSizeDPI is only available on SDL2 2.0.18 or newer

* Move the SDL2 version check in the right place

* Fix macos build
This commit is contained in:
Dimitris Panokostas 2024-10-13 16:35:35 +02:00 committed by GitHub
parent 0671a55ec9
commit 8ff8a18861
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 70 additions and 20 deletions

View File

@ -202,6 +202,7 @@ set(SOURCE_FILES
src/osdep/bsdsocket_host.cpp
src/osdep/cda_play.cpp
src/osdep/charset.cpp
src/osdep/dpi_handler.cpp
src/osdep/fsdb_host.cpp
src/osdep/clipboard.cpp
src/osdep/amiberry_hardfile.cpp

View File

@ -1306,7 +1306,6 @@ struct amiberry_gui_theme
struct amiberry_options
{
float window_scaling = 1.0;
bool quickstart_start = true;
bool read_config_descriptions = true;
bool write_logfile = false;

View File

@ -3413,9 +3413,6 @@ void save_amiberry_settings(void)
fputs(buffer, f);
};
// Set the window scaling option (the default is 1.0)
write_float_option("window_scaling", amiberry_options.window_scaling);
// Should the Quickstart Panel be the default when opening the GUI?
write_int_option("Quickstart", amiberry_options.quickstart_start);
@ -3781,7 +3778,6 @@ static int parse_amiberry_settings_line(const char *path, char *linea)
ret |= cfgfile_intval(option, value, "ROMs", &numROMs, 1);
ret |= cfgfile_intval(option, value, "MRUDiskList", &numDisks, 1);
ret |= cfgfile_intval(option, value, "MRUCDList", &numCDs, 1);
ret |= cfgfile_floatval(option, value, "window_scaling", &amiberry_options.window_scaling);
ret |= cfgfile_yesno(option, value, "Quickstart", &amiberry_options.quickstart_start);
ret |= cfgfile_yesno(option, value, "read_config_descriptions", &amiberry_options.read_config_descriptions);
ret |= cfgfile_yesno(option, value, "write_logfile", &amiberry_options.write_logfile);

View File

@ -56,6 +56,8 @@
#include "midiemu.h"
#endif
#include "dpi_handler.hpp"
#ifdef AMIBERRY
static bool force_auto_crop = false;
@ -295,8 +297,8 @@ static void SDL2_init()
mon->amiga_window = SDL_CreateWindow("Amiberry",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
800 * amiberry_options.window_scaling,
600 * amiberry_options.window_scaling,
800,
600,
mode);
}
else
@ -304,8 +306,8 @@ static void SDL2_init()
mon->amiga_window = SDL_CreateWindow("Amiberry",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
600 * amiberry_options.window_scaling,
800 * amiberry_options.window_scaling,
600,
800,
mode);
}
check_error_sdl(mon->amiga_window == nullptr, "Unable to create window:");
@ -336,6 +338,7 @@ static void SDL2_init()
mon->amiga_renderer = SDL_CreateRenderer(mon->amiga_window, -1, flags);
check_error_sdl(mon->amiga_renderer == nullptr, "Unable to create a renderer:");
}
DPIHandler::set_render_scale(mon->amiga_renderer);
#endif
if (SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, "1") != SDL_TRUE)
@ -2472,7 +2475,7 @@ bool target_graphics_buffer_update(int monid, bool force)
{
if (mon->amiga_window && isfullscreen() == 0)
{
SDL_SetWindowSize(mon->amiga_window, w * amiberry_options.window_scaling, h * amiberry_options.window_scaling);
SDL_SetWindowSize(mon->amiga_window, w, h);
}
#ifdef USE_OPENGL
renderQuad = { dx, dy, w, h };
@ -2518,7 +2521,7 @@ bool target_graphics_buffer_update(int monid, bool force)
if (mon->amiga_window && isfullscreen() == 0)
{
SDL_SetWindowSize(mon->amiga_window, scaled_width * amiberry_options.window_scaling, scaled_height * amiberry_options.window_scaling);
SDL_SetWindowSize(mon->amiga_window, scaled_width, scaled_height);
}
#ifdef USE_OPENGL
if (!currprefs.gfx_auto_crop && !currprefs.gfx_manual_crop) {

32
src/osdep/dpi_handler.cpp Normal file
View File

@ -0,0 +1,32 @@
#include "dpi_handler.hpp"
float DPIHandler::get_scale() {
constexpr int display_index{0};
const float default_dpi{96.0F};
float dpi{default_dpi};
SDL_GetDisplayDPI(display_index, nullptr, &dpi, nullptr);
return floor(dpi / default_dpi);
}
void DPIHandler::set_render_scale([[maybe_unused]] SDL_Renderer* renderer) {
// Do nothing on Linux
#ifdef __MACH__
auto scale{get_scale()};
SDL_RenderSetScale(renderer, scale, scale);
#endif
}
void DPIHandler::set_font_size(TTF_Font* font, float size) {
constexpr int display_index{0};
float hdpi{};
float vdpi{};
SDL_GetDisplayDPI(display_index, nullptr, &hdpi, &vdpi);
#if SDL_VERSION_ATLEAST(2, 0, 18)
TTF_SetFontSizeDPI(font,
static_cast<int>(size / get_scale()),
static_cast<unsigned int>(hdpi),
static_cast<unsigned int>(vdpi));
#endif
}

17
src/osdep/dpi_handler.hpp Normal file
View File

@ -0,0 +1,17 @@
#pragma once
#include "SDL.h"
#include "SDL_ttf.h"
struct WindowSize {
int width;
int height;
};
class DPIHandler {
public:
[[nodiscard]] static float get_scale();
static void set_render_scale(SDL_Renderer* renderer);
static void set_font_size(TTF_Font* font, float size);
};

View File

@ -92,8 +92,8 @@ static void InitShowMessage(const std::string& message)
mon->gui_window = SDL_CreateWindow("Amiberry GUI",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
GUI_HEIGHT * amiberry_options.window_scaling,
GUI_WIDTH * amiberry_options.window_scaling,
GUI_HEIGHT,
GUI_WIDTH,
mode);
}
else
@ -101,8 +101,8 @@ static void InitShowMessage(const std::string& message)
mon->gui_window = SDL_CreateWindow("Amiberry GUI",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
GUI_WIDTH * amiberry_options.window_scaling,
GUI_HEIGHT * amiberry_options.window_scaling,
GUI_WIDTH,
GUI_HEIGHT,
mode);
}
check_error_sdl(mon->gui_window == nullptr, "Unable to create window:");

View File

@ -3,6 +3,7 @@
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <dpi_handler.hpp>
#include <guisan.hpp>
#include <SDL_image.h>
@ -325,8 +326,8 @@ void amiberry_gui_init()
mon->gui_window = SDL_CreateWindow("Amiberry GUI",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
GUI_WIDTH * amiberry_options.window_scaling,
GUI_HEIGHT * amiberry_options.window_scaling,
GUI_WIDTH,
GUI_HEIGHT,
mode);
}
else
@ -334,8 +335,8 @@ void amiberry_gui_init()
mon->gui_window = SDL_CreateWindow("Amiberry GUI",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
GUI_HEIGHT * amiberry_options.window_scaling,
GUI_WIDTH * amiberry_options.window_scaling,
GUI_HEIGHT,
GUI_WIDTH,
mode);
}
check_error_sdl(mon->gui_window == nullptr, "Unable to create window:");
@ -349,7 +350,7 @@ void amiberry_gui_init()
}
else if (kmsdrm_detected)
{
SDL_SetWindowSize(mon->gui_window, GUI_WIDTH * amiberry_options.window_scaling, GUI_HEIGHT * amiberry_options.window_scaling);
SDL_SetWindowSize(mon->gui_window, GUI_WIDTH, GUI_HEIGHT);
}
if (mon->gui_renderer == nullptr)
@ -357,6 +358,7 @@ void amiberry_gui_init()
mon->gui_renderer = SDL_CreateRenderer(mon->gui_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
check_error_sdl(mon->gui_renderer == nullptr, "Unable to create a renderer:");
}
DPIHandler::set_render_scale(mon->gui_renderer);
// make the scaled rendering look smoother (linear scaling).
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");