diff --git a/core/hostevents.h b/core/hostevents.h index 1cf1157..03e6134 100644 --- a/core/hostevents.h +++ b/core/hostevents.h @@ -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, diff --git a/core/hostevents_sdl.cpp b/core/hostevents_sdl.cpp index 1c51221..0fe8f62 100644 --- a/core/hostevents_sdl.cpp +++ b/core/hostevents_sdl.cpp @@ -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; diff --git a/devices/video/display_sdl.cpp b/devices/video/display_sdl.cpp index 65dccbf..0245b6c 100644 --- a/devices/video/display_sdl.cpp +++ b/devices/video/display_sdl.cpp @@ -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()) { + 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(drawable_width) / width; + impl->renderer_scale_y = static_cast(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 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::functioncursor_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; }