From: Ingo Ruhnke Date: Thu, 31 Jul 2014 20:17:16 +0000 (+0200) Subject: Implemented window scaling in SDLRenderer, mouse input however breaks when scaling X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=48a97f3e160a195df0114ae976f64a9241e19bbc;p=supertux.git Implemented window scaling in SDLRenderer, mouse input however breaks when scaling --- diff --git a/src/video/sdl/sdl_renderer.cpp b/src/video/sdl/sdl_renderer.cpp index 892e39ade..106e01326 100644 --- a/src/video/sdl/sdl_renderer.cpp +++ b/src/video/sdl/sdl_renderer.cpp @@ -32,10 +32,15 @@ SDLRenderer::SDLRenderer() : window(), - renderer() + renderer(), + desktop_size() { Renderer::instance_ = this; + SDL_DisplayMode mode; + SDL_GetCurrentDisplayMode(0, &mode); + desktop_size = Size(mode.w, mode.h); + log_info << "creating SDLRenderer" << std::endl; int width = g_config->window_size.width; int height = g_config->window_size.height; @@ -201,11 +206,133 @@ SDLRenderer::flip() void SDLRenderer::resize(int w , int h) { - SCREEN_WIDTH = w; - SCREEN_HEIGHT = h; + g_config->window_size = Size(w, h); PHYSICAL_SCREEN_WIDTH = w; PHYSICAL_SCREEN_HEIGHT = h; + + apply_config(); +} + +void +SDLRenderer::apply_config() +{ + if (false) + { + log_info << "Applying Config:" + << "\n Desktop: " << desktop_size.width << "x" << desktop_size.height + << "\n Window: " << g_config->window_size + << "\n FullRes: " << g_config->fullscreen_size + << "\n Aspect: " << g_config->aspect_size + << "\n Magnif: " << g_config->magnification + << std::endl; + } + + float target_aspect = static_cast(desktop_size.width) / static_cast(desktop_size.height); + if (g_config->aspect_size != Size(0, 0)) + { + target_aspect = float(g_config->aspect_size.width) / float(g_config->aspect_size.height); + } + + float desktop_aspect = 4.0f / 3.0f; // random default fallback guess + if (desktop_size.width != -1 && desktop_size.height != -1) + { + desktop_aspect = float(desktop_size.width) / float(desktop_size.height); + } + + Size screen_size; + + // Get the screen width + if (g_config->use_fullscreen) + { + screen_size = g_config->fullscreen_size; + desktop_aspect = float(screen_size.width) / float(screen_size.height); + } + else + { + screen_size = g_config->window_size; + } + + //apply_video_mode(screen_size, g_config->use_fullscreen); + + if (target_aspect > 1.0f) + { + SCREEN_WIDTH = static_cast(screen_size.width * (target_aspect / desktop_aspect)); + SCREEN_HEIGHT = static_cast(screen_size.height); + } + else + { + SCREEN_WIDTH = static_cast(screen_size.width); + SCREEN_HEIGHT = static_cast(screen_size.height * (target_aspect / desktop_aspect)); + } + + Size max_size(1280, 800); + Size min_size(640, 480); + + if (g_config->magnification == 0.0f) // Magic value that means 'minfill' + { + // This scales SCREEN_WIDTH/SCREEN_HEIGHT so that they never excede + // max_size.width/max_size.height resp. min_size.width/min_size.height + if (SCREEN_WIDTH > max_size.width || SCREEN_HEIGHT > max_size.height) + { + float scale1 = float(max_size.width)/SCREEN_WIDTH; + float scale2 = float(max_size.height)/SCREEN_HEIGHT; + float scale = (scale1 < scale2) ? scale1 : scale2; + SCREEN_WIDTH = static_cast(SCREEN_WIDTH * scale); + SCREEN_HEIGHT = static_cast(SCREEN_HEIGHT * scale); + } + else if (SCREEN_WIDTH < min_size.width || SCREEN_HEIGHT < min_size.height) + { + float scale1 = float(min_size.width)/SCREEN_WIDTH; + float scale2 = float(min_size.height)/SCREEN_HEIGHT; + float scale = (scale1 < scale2) ? scale1 : scale2; + SCREEN_WIDTH = static_cast(SCREEN_WIDTH * scale); + SCREEN_HEIGHT = static_cast(SCREEN_HEIGHT * scale); + } + + SDL_Rect viewport; + viewport.x = 0; + viewport.y = 0; + viewport.w = screen_size.width; + viewport.h = screen_size.height; + SDL_RenderSetViewport(renderer, &viewport); + } + else + { + SCREEN_WIDTH = static_cast(SCREEN_WIDTH / g_config->magnification); + SCREEN_HEIGHT = static_cast(SCREEN_HEIGHT / g_config->magnification); + + // This works by adding black borders around the screen to limit + // SCREEN_WIDTH/SCREEN_HEIGHT to max_size.width/max_size.height + Size new_size = screen_size; + + if (SCREEN_WIDTH > max_size.width) + { + new_size.width = static_cast((float) new_size.width * float(max_size.width)/SCREEN_WIDTH); + SCREEN_WIDTH = static_cast(max_size.width); + } + + if (SCREEN_HEIGHT > max_size.height) + { + new_size.height = static_cast((float) new_size.height * float(max_size.height)/SCREEN_HEIGHT); + SCREEN_HEIGHT = static_cast(max_size.height); + } + + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE); + SDL_RenderClear(renderer); + SDL_RenderPresent(renderer); + SDL_RenderClear(renderer); + + SDL_Rect viewport; + viewport.x = std::max(0, (screen_size.width - new_size.width) / 2); + viewport.y = std::max(0, (screen_size.height - new_size.height) / 2); + viewport.w = std::min(new_size.width, screen_size.width); + viewport.h = std::min(new_size.height, screen_size.height); + SDL_RenderSetViewport(renderer, &viewport); + } + + SDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT); } void diff --git a/src/video/sdl/sdl_renderer.hpp b/src/video/sdl/sdl_renderer.hpp index 67dd321f4..4c8a62c44 100644 --- a/src/video/sdl/sdl_renderer.hpp +++ b/src/video/sdl/sdl_renderer.hpp @@ -34,7 +34,7 @@ public: void do_take_screenshot(); void flip(); void resize(int w, int h); - void apply_config() {} + void apply_config(); void set_gamma(float gamma); SDL_Window* get_window() const { return window; } @@ -43,6 +43,7 @@ public: private: SDL_Window* window; SDL_Renderer* renderer; + Size desktop_size; private: SDLRenderer(const SDLRenderer&);