Skip to content

Commit

Permalink
Merge pull request #118 from mihaip/upstream-hidpi
Browse files Browse the repository at this point in the history
Enable HiDPI mode for SDL and ensure that we use nearest-neighbor scaling
  • Loading branch information
dingusdev authored Nov 9, 2024
2 parents 27d389c + fc13f68 commit 6766ca8
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 7 deletions.
6 changes: 6 additions & 0 deletions core/hostevents.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ class WindowEvent {
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,
Expand Down
14 changes: 12 additions & 2 deletions core/hostevents_sdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
28 changes: 23 additions & 5 deletions devices/video/display_sdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ class Display::Impl {
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() {
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
}

0 comments on commit 6766ca8

Please sign in to comment.