Replaced SDL_RenderSetLogicalSize(), removed PHYSICAL_SCREEN_WIDTH/HEIGHT, improved...
authorIngo Ruhnke <grumbel@gmail.com>
Fri, 1 Aug 2014 17:25:17 +0000 (19:25 +0200)
committerIngo Ruhnke <grumbel@gmail.com>
Fri, 1 Aug 2014 17:25:17 +0000 (19:25 +0200)
src/supertux/globals.cpp
src/supertux/globals.hpp
src/video/gl/gl_renderer.cpp
src/video/gl/gl_renderer.hpp
src/video/sdl/sdl_renderer.cpp
src/video/sdl/sdl_renderer.hpp

index 6b27112..207c119 100644 (file)
@@ -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;
index 6962ef0..8902619 100644 (file)
@@ -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;
 
index 9cf568c..599eb53 100644 (file)
@@ -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<int>(SCREEN_WIDTH  * scale);
       SCREEN_HEIGHT = static_cast<int>(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<int>(SCREEN_WIDTH  * scale);
       SCREEN_HEIGHT = static_cast<int>(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<float>(physical_x - viewport.x) * SCREEN_WIDTH / viewport.w,
+                static_cast<float>(physical_y - viewport.y) * SCREEN_HEIGHT / viewport.h);
 }
 
 void
index dd70308..d1b7026 100644 (file)
@@ -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:
index 6708ffe..736b299 100644 (file)
@@ -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<int>(SCREEN_WIDTH  * scale);
-      SCREEN_HEIGHT = static_cast<int>(SCREEN_HEIGHT * scale);
-    } 
+      magnification = (scale1 < scale2) ? scale1 : scale2;
+      SCREEN_WIDTH  = static_cast<int>(SCREEN_WIDTH  * magnification);
+      SCREEN_HEIGHT = static_cast<int>(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<int>(SCREEN_WIDTH  * scale);
-      SCREEN_HEIGHT = static_cast<int>(SCREEN_HEIGHT * scale);
+      magnification = (scale1 < scale2) ? scale1 : scale2;
+      SCREEN_WIDTH  = static_cast<int>(SCREEN_WIDTH  * magnification);
+      SCREEN_HEIGHT = static_cast<int>(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<int>((float) new_size.height * float(max_size.height)/SCREEN_HEIGHT);
       SCREEN_HEIGHT = static_cast<int>(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<float>(physical_x - viewport.x) * SCREEN_WIDTH / viewport.w,
+                static_cast<float>(physical_y - viewport.y) * SCREEN_HEIGHT / viewport.h);
 }
 
 void
index a9159ec..ef8607e 100644 (file)
@@ -44,6 +44,7 @@ public:
 private:
   SDL_Window* window;
   SDL_Renderer* renderer;
+  SDL_Rect viewport;
   Size desktop_size;
 
 private: