From 681723869fffbd287982efc0b323aa8444ec2bdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Mon, 9 Nov 2015 00:02:51 +0100 Subject: [PATCH] Enable display scaling, useful on highdpi screens This allows for NN-scaling of display, a much needed feature on highdpi screens. Scale can be set to positive integer value which will become a zoom factor for whole rendered output. --- distribution/changelog.txt | 3 +- src/config.c | 1 + src/config.h | 1 + src/platform/shared.c | 62 ++++++++++++++++++++++++++------------ 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 37a315ef8e..0b54cb2da6 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -28,7 +28,7 @@ - Feature: Custom user data path specified by command line argument. - Feature: Full UTF-8 language support. - Feature: TTF font integration for non-Latin languages. -- Feature: Added support for Traditional Chinese, Simplified Chinese, Korean, Russian, Finnish and Brazilian Portuguese. +- Feature: Added support for Traditional Chinese, Simplified Chinese, Korean, Russian, Finnish and Brazilian Portuguese. - Feature: Added South Korean Won and Russian Rouble as currencies. - Feature: Allow different date formats. - Feature: Option to automatically pause the game on minimise from fullscreen. @@ -38,6 +38,7 @@ - Feature: Option to automatically place staff after hire. - Feature: Option to enable 'mow grass' by default for handymen (RCT1 style) - Feature: Option to ignore invalid checksums on loaded parks. +- Feature: Option to scale game display for better compatibility with high DPI screens. - Alteration: Autosave is now measured in real-time rather than in-game date. - Technical: DirectDraw, DirectInput, DirectPlay and DirectSound dependencies are no longer used. - Removed: Six Flags branding and limitations. diff --git a/src/config.c b/src/config.c index 647f59e4f7..57530c1df1 100644 --- a/src/config.c +++ b/src/config.c @@ -197,6 +197,7 @@ config_property_definition _generalDefinitions[] = { { offsetof(general_configuration, upper_case_banners), "upper_case_banners", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, allow_loading_with_incorrect_checksum),"allow_loading_with_incorrect_checksum", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, steam_overlay_pause), "steam_overlay_pause", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(general_configuration, scale), "scale", CONFIG_VALUE_TYPE_SINT8, 1, NULL }, }; config_property_definition _interfaceDefinitions[] = { diff --git a/src/config.h b/src/config.h index 58dae6b559..fba4ab4779 100644 --- a/src/config.h +++ b/src/config.h @@ -167,6 +167,7 @@ typedef struct { uint8 upper_case_banners; uint8 allow_loading_with_incorrect_checksum; uint8 steam_overlay_pause; + sint8 scale; } general_configuration; typedef struct { diff --git a/src/platform/shared.c b/src/platform/shared.c index 71bbc88033..a98a4f98aa 100644 --- a/src/platform/shared.c +++ b/src/platform/shared.c @@ -65,8 +65,9 @@ bool gHardwareDisplay; bool gSteamOverlayActive = false; -static SDL_Surface *_surface; -static SDL_Palette *_palette; +static SDL_Surface *_surface = NULL; +static SDL_Surface *_RGBASurface = NULL; +static SDL_Palette *_palette = NULL; static void *_screenBuffer; static int _screenBufferSize; @@ -285,9 +286,24 @@ void platform_draw() SDL_UnlockSurface(_surface); // Copy the surface to the window - if (SDL_BlitSurface(_surface, NULL, SDL_GetWindowSurface(gWindow), NULL)) { - log_fatal("SDL_BlitSurface %s", SDL_GetError()); - exit(1); + if (gConfigGeneral.scale == 1 || gConfigGeneral.scale <= 0) + { + if (SDL_BlitSurface(_surface, NULL, SDL_GetWindowSurface(gWindow), NULL)) { + log_fatal("SDL_BlitSurface %s", SDL_GetError()); + exit(1); + } + } else { + // first blit to rgba surface to change the pixel format + if (SDL_BlitSurface(_surface, NULL, _RGBASurface, NULL)) { + log_fatal("SDL_BlitSurface %s", SDL_GetError()); + exit(1); + } + // then scale to window size. Without changing to RGBA first, SDL complains + // about blit configurations being incompatible. + if (SDL_BlitScaled(_RGBASurface, NULL, SDL_GetWindowSurface(gWindow), NULL)) { + log_fatal("SDL_BlitScaled %s", SDL_GetError()); + exit(1); + } } if (SDL_UpdateWindowSurface(gWindow)) { log_fatal("SDL_UpdateWindowSurface %s", SDL_GetError()); @@ -300,17 +316,19 @@ void platform_draw() static void platform_resize(int width, int height) { uint32 flags; + int dst_w = width / gConfigGeneral.scale; + int dst_h = height / gConfigGeneral.scale; - RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) = width; - RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) = height; + RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) = dst_w; + RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) = dst_h; platform_refresh_video(); flags = SDL_GetWindowFlags(gWindow); if ((flags & SDL_WINDOW_MINIMIZED) == 0) { - window_resize_gui(width, height); - window_relocate_windows(width, height); + window_resize_gui(dst_w, dst_h); + window_relocate_windows(dst_w, dst_h); } title_fix_location(); @@ -421,11 +439,11 @@ void platform_process_messages() } break; case SDL_MOUSEMOTION: - RCT2_GLOBAL(0x0142406C, int) = e.motion.x; - RCT2_GLOBAL(0x01424070, int) = e.motion.y; + RCT2_GLOBAL(0x0142406C, int) = e.motion.x / gConfigGeneral.scale; + RCT2_GLOBAL(0x01424070, int) = e.motion.y / gConfigGeneral.scale; - gCursorState.x = e.motion.x; - gCursorState.y = e.motion.y; + gCursorState.x = e.motion.x / gConfigGeneral.scale; + gCursorState.y = e.motion.y / gConfigGeneral.scale; break; case SDL_MOUSEWHEEL: if (gConsoleOpen) { @@ -435,8 +453,8 @@ void platform_process_messages() gCursorState.wheel += e.wheel.y * 128; break; case SDL_MOUSEBUTTONDOWN: - RCT2_GLOBAL(0x01424318, int) = e.button.x; - RCT2_GLOBAL(0x0142431C, int) = e.button.y; + RCT2_GLOBAL(0x01424318, int) = e.button.x / gConfigGeneral.scale; + RCT2_GLOBAL(0x0142431C, int) = e.button.y / gConfigGeneral.scale; switch (e.button.button) { case SDL_BUTTON_LEFT: store_mouse_input(1); @@ -454,8 +472,8 @@ void platform_process_messages() } break; case SDL_MOUSEBUTTONUP: - RCT2_GLOBAL(0x01424318, int) = e.button.x; - RCT2_GLOBAL(0x0142431C, int) = e.button.y; + RCT2_GLOBAL(0x01424318, int) = e.button.x / gConfigGeneral.scale; + RCT2_GLOBAL(0x0142431C, int) = e.button.y / gConfigGeneral.scale; switch (e.button.button) { case SDL_BUTTON_LEFT: store_mouse_input(2); @@ -644,6 +662,8 @@ static void platform_close_window() SDL_FreeSurface(_surface); if (_palette != NULL) SDL_FreePalette(_palette); + if (_RGBASurface != NULL) + SDL_FreeSurface(_RGBASurface); platform_unload_cursors(); } @@ -916,14 +936,18 @@ void platform_refresh_video() } else { if (_surface != NULL) SDL_FreeSurface(_surface); + if (_RGBASurface != NULL) + SDL_FreeSurface(_RGBASurface); if (_palette != NULL) SDL_FreePalette(_palette); _surface = SDL_CreateRGBSurface(0, width, height, 8, 0, 0, 0, 0); + _RGBASurface = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0); + SDL_SetSurfaceBlendMode(_RGBASurface, SDL_BLENDMODE_NONE); _palette = SDL_AllocPalette(256); - if (!_surface || !_palette) { - log_fatal("%p || %p == NULL %s", _surface, _palette, SDL_GetError()); + if (!_surface || !_palette || !_RGBASurface) { + log_fatal("%p || %p || %p == NULL %s", _surface, _palette, _RGBASurface, SDL_GetError()); exit(-1); }