Merge pull request #118 from mihaip/upstream-hidpi

Enable HiDPI mode for SDL and ensure that we use nearest-neighbor scaling
This commit is contained in:
dingusdev 2024-11-09 16:59:15 -07:00 committed by GitHub
commit 6766ca8647
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 41 additions and 7 deletions

View File

@ -35,6 +35,12 @@ public:
uint32_t window_id;
};
enum : uint16_t {
// Standard SDL window event types are uint8_t's, we add our own custom
// events after that.
WINDOW_SCALE_QUALITY_TOGGLE = 1 << 8,
};
enum : uint32_t {
MOUSE_EVENT_MOTION = 1 << 0,
MOUSE_EVENT_BUTTON = 1 << 1,

View File

@ -54,14 +54,24 @@ void EventManager::poll_events()
case SDL_KEYDOWN:
case SDL_KEYUP: {
// Internal shortcuts to trigger mouse grab, intentionally not
// sent to the host.
// Internal shortcuts, intentionally not sent to the host.
// Control-G: mouse grab
if (event.key.keysym.sym == SDLK_g && SDL_GetModState() & KMOD_LCTRL) {
if (event.type == SDL_KEYUP) {
toggle_mouse_grab(event.key);
}
return;
}
// Control-S: scale quality
if (event.key.keysym.sym == SDLK_s && SDL_GetModState() & KMOD_LCTRL) {
if (event.type == SDL_KEYUP) {
WindowEvent we;
we.sub_type = WINDOW_SCALE_QUALITY_TOGGLE;
we.window_id = event.window.windowID;
this->_window_signal.emit(we);
}
return;
}
int key_code = get_sdl_event_key_code(event.key);
if (key_code != -1) {
KeyboardEvent ke;

View File

@ -29,12 +29,15 @@ public:
uint32_t disp_wnd_id = 0;
SDL_Window* display_wnd = 0;
SDL_Renderer* renderer = 0;
double renderer_scale_x; // scaling factor from guest OS to host OS
double renderer_scale_y;
SDL_Texture* disp_texture = 0;
SDL_Texture* cursor_texture = 0;
SDL_Rect cursor_rect; // destination rectangle for cursor drawing
};
Display::Display(): impl(std::make_unique<Impl>()) {
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
}
Display::~Display() {
@ -61,7 +64,7 @@ bool Display::configure(int width, int height) {
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
width, height,
SDL_WINDOW_OPENGL
SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI
);
impl->disp_wnd_id = SDL_GetWindowID(impl->display_wnd);
@ -72,6 +75,11 @@ bool Display::configure(int width, int height) {
if (impl->renderer == NULL)
ABORT_F("Display: SDL_CreateRenderer failed with %s", SDL_GetError());
int drawable_width, drawable_height;
SDL_GetRendererOutputSize(impl->renderer, &drawable_width, &drawable_height);
impl->renderer_scale_x = static_cast<double>(drawable_width) / width;
impl->renderer_scale_y = static_cast<float>(drawable_height) / height;
is_initialization = true;
} else { // resize display window
SDL_SetWindowSize(impl->display_wnd, width, height);
@ -100,6 +108,16 @@ void Display::handle_events(const WindowEvent& wnd_event) {
if (wnd_event.sub_type == SDL_WINDOWEVENT_EXPOSED &&
wnd_event.window_id == impl->disp_wnd_id)
SDL_RenderPresent(impl->renderer);
if (wnd_event.sub_type == WINDOW_SCALE_QUALITY_TOGGLE &&
wnd_event.window_id == impl->disp_wnd_id) {
auto current_quality = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
auto new_quality = current_quality == NULL || strcmp(current_quality, "nearest") == 0 ? "best" : "nearest";
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, new_quality);
// We need the window/texture to be recreated to pick up the hint change.
int width, height;
SDL_GetWindowSize(impl->display_wnd, &width, &height);
this->configure(width, height);
}
}
void Display::blank() {
@ -133,8 +151,8 @@ void Display::update(std::function<void(uint8_t *dst_buf, int dst_pitch)> conver
// draw HW cursor if enabled
if (draw_hw_cursor) {
impl->cursor_rect.x = cursor_x;
impl->cursor_rect.y = cursor_y;
impl->cursor_rect.x = cursor_x * impl->renderer_scale_x;
impl->cursor_rect.y = cursor_y * impl->renderer_scale_y;
SDL_RenderCopy(impl->renderer, impl->cursor_texture, NULL, &impl->cursor_rect);
}
@ -170,6 +188,6 @@ void Display::setup_hw_cursor(std::function<void(uint8_t *dst_buf, int dst_pitch
impl->cursor_rect.x = 0;
impl->cursor_rect.y = 0;
impl->cursor_rect.w = cursor_width;
impl->cursor_rect.h = cursor_height;
impl->cursor_rect.w = cursor_width * impl->renderer_scale_x;
impl->cursor_rect.h = cursor_height * impl->renderer_scale_y;
}