From a432e4ee35a0219c8983fc75d1e83dfad51167fa Mon Sep 17 00:00:00 2001 From: Ingo Ruhnke Date: Fri, 1 Aug 2014 19:25:17 +0200 Subject: [PATCH] Replaced SDL_RenderSetLogicalSize(), removed PHYSICAL_SCREEN_WIDTH/HEIGHT, improved mouse handling when using magnification --- src/supertux/globals.cpp | 3 -- src/supertux/globals.hpp | 3 -- src/video/gl/gl_renderer.cpp | 50 ++++++++++++++-------------- src/video/gl/gl_renderer.hpp | 9 ++--- src/video/sdl/sdl_renderer.cpp | 74 +++++++++++++++++++++++++----------------- src/video/sdl/sdl_renderer.hpp | 1 + 6 files changed, 75 insertions(+), 65 deletions(-) diff --git a/src/supertux/globals.cpp b/src/supertux/globals.cpp index 6b2711204..207c119d8 100644 --- a/src/supertux/globals.cpp +++ b/src/supertux/globals.cpp @@ -23,9 +23,6 @@ tinygettext::DictionaryManager* dictionary_manager = 0; int SCREEN_WIDTH; int SCREEN_HEIGHT; -int PHYSICAL_SCREEN_WIDTH; -int PHYSICAL_SCREEN_HEIGHT; - ScreenManager* g_screen_manager = 0; TextureManager* texture_manager = 0; diff --git a/src/supertux/globals.hpp b/src/supertux/globals.hpp index 6962ef0c4..890261947 100644 --- a/src/supertux/globals.hpp +++ b/src/supertux/globals.hpp @@ -39,9 +39,6 @@ extern int SCREEN_WIDTH; shrink or scale things) */ extern int SCREEN_HEIGHT; -extern int PHYSICAL_SCREEN_WIDTH; -extern int PHYSICAL_SCREEN_HEIGHT; - // global variables extern JoystickKeyboardController* g_jk_controller; diff --git a/src/video/gl/gl_renderer.cpp b/src/video/gl/gl_renderer.cpp index 9cf568c28..599eb5343 100644 --- a/src/video/gl/gl_renderer.cpp +++ b/src/video/gl/gl_renderer.cpp @@ -87,12 +87,12 @@ GLRenderer::GLRenderer() : // Init the projection matrix, viewport and stuff apply_config(); - + if(texture_manager == 0) texture_manager = new TextureManager(); else texture_manager->reload_textures(); - + #ifndef GL_VERSION_ES_CM_1_0 GLenum err = glewInit(); if (GLEW_OK != err) @@ -189,7 +189,7 @@ GLRenderer::draw_surface_part(const DrawingRequest& request) void GLRenderer::draw_gradient(const DrawingRequest& request) { - const GradientRequest* gradientrequest + const GradientRequest* gradientrequest = (GradientRequest*) request.request_data; const Color& top = gradientrequest->top; const Color& bottom = gradientrequest->bottom; @@ -233,7 +233,7 @@ GLRenderer::draw_filled_rect(const DrawingRequest& request) glColor4f(fillrectrequest->color.red, fillrectrequest->color.green, fillrectrequest->color.blue, fillrectrequest->color.alpha); glDisableClientState(GL_TEXTURE_COORD_ARRAY); - + if (fillrectrequest->radius != 0.0f) { // draw round rect @@ -311,7 +311,7 @@ GLRenderer::draw_inverse_ellipse(const DrawingRequest& request) glDisable(GL_TEXTURE_2D); glColor4f(ellipse->color.red, ellipse->color.green, ellipse->color.blue, ellipse->color.alpha); - + float x = request.pos.x; float y = request.pos.y; float w = ellipse->size.x/2.0f; @@ -380,10 +380,10 @@ GLRenderer::draw_inverse_ellipse(const DrawingRequest& request) glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnable(GL_TEXTURE_2D); - glColor4f(1, 1, 1, 1); + glColor4f(1, 1, 1, 1); } -void +void GLRenderer::do_take_screenshot() { // [Christoph] TODO: Yes, this method also takes care of the actual disk I/O. Split it? @@ -464,18 +464,15 @@ GLRenderer::resize(int w, int h) { g_config->window_size = Size(w, h); - PHYSICAL_SCREEN_WIDTH = w; - PHYSICAL_SCREEN_HEIGHT = h; - apply_config(); } void GLRenderer::apply_config() -{ +{ if (false) { - log_info << "Applying Config:" + 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 @@ -536,7 +533,7 @@ GLRenderer::apply_config() 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; @@ -545,9 +542,13 @@ GLRenderer::apply_config() SCREEN_WIDTH = static_cast(SCREEN_WIDTH * scale); SCREEN_HEIGHT = static_cast(SCREEN_HEIGHT * scale); } - - glViewport(0, 0, screen_size.width, screen_size.height); + viewport.x = 0; + viewport.y = 0; + viewport.w = screen_size.width; + viewport.h = screen_size.height; + + glViewport(viewport.x, viewport.y, viewport.w, viewport.h); } else { @@ -576,10 +577,12 @@ GLRenderer::apply_config() glClear(GL_COLOR_BUFFER_BIT); SDL_GL_SwapWindow(window); - glViewport(std::max(0, (screen_size.width - new_size.width) / 2), - std::max(0, (screen_size.height - new_size.height) / 2), - std::min(new_size.width, screen_size.width), - std::min(new_size.height, screen_size.height)); + 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); + + glViewport(viewport.x, viewport.y, viewport.w, viewport.h); } glMatrixMode(GL_PROJECTION); @@ -652,13 +655,10 @@ GLRenderer::apply_video_mode(const Size& size, bool fullscreen) { glcontext = SDL_GL_CreateContext(window); screen_size = size; - - PHYSICAL_SCREEN_WIDTH = size.width; - PHYSICAL_SCREEN_HEIGHT = size.height; SCREEN_WIDTH = size.width; SCREEN_HEIGHT = size.height; - + fullscreen_active = fullscreen; } } @@ -667,8 +667,8 @@ GLRenderer::apply_video_mode(const Size& size, bool fullscreen) Vector GLRenderer::to_logical(int physical_x, int physical_y) { - return Vector(physical_x * float(SCREEN_WIDTH) / PHYSICAL_SCREEN_WIDTH, - physical_y * float(SCREEN_HEIGHT) / PHYSICAL_SCREEN_HEIGHT); + return Vector(static_cast(physical_x - viewport.x) * SCREEN_WIDTH / viewport.w, + static_cast(physical_y - viewport.y) * SCREEN_HEIGHT / viewport.h); } void diff --git a/src/video/gl/gl_renderer.hpp b/src/video/gl/gl_renderer.hpp index dd7030816..d1b7026e9 100644 --- a/src/video/gl/gl_renderer.hpp +++ b/src/video/gl/gl_renderer.hpp @@ -36,13 +36,13 @@ inline void intern_draw(float left, float top, float right, float bottom, { if(effect & HORIZONTAL_FLIP) std::swap(uv_left, uv_right); - - if(effect & VERTICAL_FLIP) + + if(effect & VERTICAL_FLIP) std::swap(uv_top, uv_bottom); glBlendFunc(blend.sfactor, blend.dfactor); glColor4f(color.red, color.green, color.blue, color.alpha * alpha); - + // unrotated blit if (angle == 0.0f) { float vertices[] = { @@ -109,10 +109,11 @@ class GLRenderer : public Renderer private: SDL_Window* window; SDL_GLContext glcontext; + SDL_Rect viewport; Size desktop_size; Size screen_size; bool fullscreen_active; - + GLuint last_texture; public: diff --git a/src/video/sdl/sdl_renderer.cpp b/src/video/sdl/sdl_renderer.cpp index 6708ffe85..736b299f2 100644 --- a/src/video/sdl/sdl_renderer.cpp +++ b/src/video/sdl/sdl_renderer.cpp @@ -33,6 +33,7 @@ SDLRenderer::SDLRenderer() : window(), renderer(), + viewport(), desktop_size() { Renderer::instance_ = this; @@ -56,8 +57,10 @@ SDLRenderer::SDLRenderer() : SCREEN_WIDTH = width; SCREEN_HEIGHT = height; - PHYSICAL_SCREEN_WIDTH = width; - PHYSICAL_SCREEN_HEIGHT = height; + viewport.x = 0; + viewport.y = 0; + viewport.w = SCREEN_WIDTH; + viewport.h = SCREEN_HEIGHT; SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2"); @@ -135,7 +138,7 @@ SDLRenderer::draw_inverse_ellipse(const DrawingRequest& request) SDLPainter::draw_inverse_ellipse(renderer, request); } -void +void SDLRenderer::do_take_screenshot() { // [Christoph] TODO: Yes, this method also takes care of the actual disk I/O. Split it? @@ -212,9 +215,6 @@ SDLRenderer::resize(int w , int h) { g_config->window_size = Size(w, h); - PHYSICAL_SCREEN_WIDTH = w; - PHYSICAL_SCREEN_HEIGHT = h; - apply_config(); } @@ -223,7 +223,7 @@ SDLRenderer::apply_config() { if (false) { - log_info << "Applying Config:" + 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 @@ -298,24 +298,35 @@ SDLRenderer::apply_config() if (g_config->magnification == 0.0f) // Magic value that means 'minfill' { + float magnification = 1.0f; + // 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); - } + magnification = (scale1 < scale2) ? scale1 : scale2; + SCREEN_WIDTH = static_cast(SCREEN_WIDTH * magnification); + SCREEN_HEIGHT = static_cast(SCREEN_HEIGHT * magnification); + } 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); + magnification = (scale1 < scale2) ? scale1 : scale2; + SCREEN_WIDTH = static_cast(SCREEN_WIDTH * magnification); + SCREEN_HEIGHT = static_cast(SCREEN_HEIGHT * magnification); } + + viewport.x = 0; + viewport.y = 0; + viewport.w = screen_size.width; + viewport.h = screen_size.height; + + SDL_RenderSetScale(renderer, 1.0f, 1.0f); + SDL_RenderSetViewport(renderer, &viewport); + SDL_RenderSetScale(renderer, magnification, magnification); } else { @@ -337,28 +348,31 @@ SDLRenderer::apply_config() new_size.height = static_cast((float) new_size.height * float(max_size.height)/SCREEN_HEIGHT); SCREEN_HEIGHT = static_cast(max_size.height); } - } - // Clear the screen to avoid garbage in unreachable areas after we - // reset the coordinate system - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); - SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE); - SDL_RenderClear(renderer); - SDL_RenderPresent(renderer); - SDL_RenderClear(renderer); - - // This doesn't really do what we want, as it sales the area to fill - // the screen, but seems to be the only way to reset the coordinate - // system and it's "close enough" to what we want, see: - // https://bugzilla.libsdl.org/show_bug.cgi?id=2179 - SDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT); + // Clear the screen to avoid garbage in unreachable areas after we + // reset the coordinate system + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE); + SDL_RenderClear(renderer); + SDL_RenderPresent(renderer); + SDL_RenderClear(renderer); + + 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_RenderSetScale(renderer, 1.0f, 1.0f); + SDL_RenderSetViewport(renderer, &viewport); + SDL_RenderSetScale(renderer, g_config->magnification, g_config->magnification); + } } Vector SDLRenderer::to_logical(int physical_x, int physical_y) { - // SDL is doing the translation internally, so we have nothing to do - return Vector(physical_x, physical_y); + return Vector(static_cast(physical_x - viewport.x) * SCREEN_WIDTH / viewport.w, + static_cast(physical_y - viewport.y) * SCREEN_HEIGHT / viewport.h); } void diff --git a/src/video/sdl/sdl_renderer.hpp b/src/video/sdl/sdl_renderer.hpp index a9159ec81..ef8607eec 100644 --- a/src/video/sdl/sdl_renderer.hpp +++ b/src/video/sdl/sdl_renderer.hpp @@ -44,6 +44,7 @@ public: private: SDL_Window* window; SDL_Renderer* renderer; + SDL_Rect viewport; Size desktop_size; private: -- 2.11.0