Skip to content

Commit

Permalink
Reimplemented magnification and aspect ratio handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Grumbel committed Aug 2, 2014
1 parent 6c15389 commit 4641bbe
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 166 deletions.
79 changes: 15 additions & 64 deletions src/video/gl/gl_renderer.cpp
Expand Up @@ -27,6 +27,8 @@
#include "video/drawing_request.hpp"
#include "video/gl/gl_surface_data.hpp"
#include "video/gl/gl_texture.hpp"
#include "video/util.hpp"

#define LIGHTMAP_DIV 5

#ifdef GL_VERSION_ES_CM_1_0
Expand Down Expand Up @@ -508,83 +510,32 @@ GLRenderer::apply_config()

apply_video_mode(screen_size, g_config->use_fullscreen);

if (target_aspect > 1.0f)
{
SCREEN_WIDTH = static_cast<int>(screen_size.width * (target_aspect / desktop_aspect));
SCREEN_HEIGHT = static_cast<int>(screen_size.height);
}
else
{
SCREEN_WIDTH = static_cast<int>(screen_size.width);
SCREEN_HEIGHT = static_cast<int>(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<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;
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);
}
Vector scale;
Size logical_size;
calculate_viewport(min_size, max_size,
screen_size,
target_aspect / desktop_aspect, g_config->magnification,
scale,
logical_size,
viewport);

viewport.x = 0;
viewport.y = 0;
viewport.w = screen_size.width;
viewport.h = screen_size.height;
SCREEN_WIDTH = logical_size.width;
SCREEN_HEIGHT = logical_size.height;

glViewport(viewport.x, viewport.y, viewport.w, viewport.h);
}
else
if (viewport.x != 0 || viewport.y != 0)
{
SCREEN_WIDTH = static_cast<int>(SCREEN_WIDTH / g_config->magnification);
SCREEN_HEIGHT = static_cast<int>(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<int>((float) new_size.width * float(max_size.width)/SCREEN_WIDTH);
SCREEN_WIDTH = static_cast<int>(max_size.width);
}

if (SCREEN_HEIGHT > max_size.height)
{
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 both buffers so that we get a clean black border without junk
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(window);
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(window);

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);
}

glViewport(viewport.x, viewport.y, viewport.w, viewport.h);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

Expand Down
155 changes: 54 additions & 101 deletions src/video/sdl/sdl_renderer.cpp
Expand Up @@ -30,6 +30,8 @@
#include <stdexcept>
#include "SDL2/SDL_video.h"

#include "video/util.hpp"

SDLRenderer::SDLRenderer() :
window(),
renderer(),
Expand All @@ -39,7 +41,7 @@ SDLRenderer::SDLRenderer() :
Renderer::instance_ = this;

SDL_DisplayMode mode;
SDL_GetCurrentDisplayMode(0, &mode);
SDL_GetDesktopDisplayMode(0, &mode);
desktop_size = Size(mode.w, mode.h);

log_info << "creating SDLRenderer" << std::endl;
Expand All @@ -59,8 +61,8 @@ SDLRenderer::SDLRenderer() :

viewport.x = 0;
viewport.y = 0;
viewport.w = SCREEN_WIDTH;
viewport.h = SCREEN_HEIGHT;
viewport.w = width;
viewport.h = height;

SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");

Expand Down Expand Up @@ -99,6 +101,7 @@ SDLRenderer::SDLRenderer() :
if(texture_manager == 0)
texture_manager = new TextureManager();

g_config->window_size = Size(width, height);
apply_config();
}

Expand Down Expand Up @@ -219,44 +222,8 @@ SDLRenderer::resize(int w , int h)
}

void
SDLRenderer::apply_config()
SDLRenderer::apply_video_mode()
{
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<float>(desktop_size.width) / static_cast<float>(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;
}

if (!g_config->use_fullscreen)
{
SDL_SetWindowFullscreen(window, 0);
Expand All @@ -282,90 +249,76 @@ SDLRenderer::apply_config()
}
}

if (target_aspect > 1.0f)
}

void
SDLRenderer::apply_viewport()
{
// calculate the aspect ratio
float target_aspect = static_cast<float>(desktop_size.width) / static_cast<float>(desktop_size.height);
if (g_config->aspect_size != Size(0, 0))
{
SCREEN_WIDTH = static_cast<int>(screen_size.width * (target_aspect / desktop_aspect));
SCREEN_HEIGHT = static_cast<int>(screen_size.height);
target_aspect = float(g_config->aspect_size.width) / float(g_config->aspect_size.height);
}
else

float desktop_aspect = 4.0f / 3.0f; // random default fallback guess
if (desktop_size.width != -1 && desktop_size.height != -1)
{
SCREEN_WIDTH = static_cast<int>(screen_size.width);
SCREEN_HEIGHT = static_cast<int>(screen_size.height * (target_aspect / desktop_aspect));
desktop_aspect = float(desktop_size.width) / float(desktop_size.height);
}

Size max_size(1280, 800);
Size min_size(640, 480);
Size screen_size;

if (g_config->magnification == 0.0f) // Magic value that means 'minfill'
// Get the screen width
if (g_config->use_fullscreen)
{
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;
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;
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);
screen_size = g_config->fullscreen_size;
desktop_aspect = float(screen_size.width) / float(screen_size.height);
}
else
{
SCREEN_WIDTH = static_cast<int>(SCREEN_WIDTH / g_config->magnification);
SCREEN_HEIGHT = static_cast<int>(SCREEN_HEIGHT / g_config->magnification);
screen_size = g_config->window_size;
}

// 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;
// calculate the viewport
Size max_size(1280, 800);
Size min_size(640, 480);

if (SCREEN_WIDTH > max_size.width)
{
new_size.width = static_cast<int>((float) new_size.width * float(max_size.width)/SCREEN_WIDTH);
SCREEN_WIDTH = static_cast<int>(max_size.width);
}
// FIXME: don't do this, save window size
Size window_size;
SDL_GetWindowSize(window, &window_size.width, &window_size.height);

if (SCREEN_HEIGHT > max_size.height)
{
new_size.height = static_cast<int>((float) new_size.height * float(max_size.height)/SCREEN_HEIGHT);
SCREEN_HEIGHT = static_cast<int>(max_size.height);
}
Vector scale;
Size logical_size;
calculate_viewport(min_size, max_size, window_size,
target_aspect / desktop_aspect,
g_config->magnification,
scale, logical_size, viewport);

SCREEN_WIDTH = logical_size.width;
SCREEN_HEIGHT = logical_size.height;

if (viewport.x != 0 || viewport.y != 0)
{
// 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, scale.x, scale.y);
}

SDL_RenderSetScale(renderer, 1.0f, 1.0f);
SDL_RenderSetViewport(renderer, &viewport);
SDL_RenderSetScale(renderer, g_config->magnification, g_config->magnification);
}
void
SDLRenderer::apply_config()
{
apply_video_mode();
apply_viewport();
}

Vector
Expand Down
5 changes: 4 additions & 1 deletion src/video/sdl/sdl_renderer.hpp
Expand Up @@ -38,9 +38,12 @@ class SDLRenderer : public Renderer
Vector to_logical(int physical_x, int physical_y);
void set_gamma(float gamma);
SDL_Window* get_window() const { return window; }

SDL_Renderer* get_sdl_renderer() const { return renderer; };

private:
void apply_video_mode();
void apply_viewport();

private:
SDL_Window* window;
SDL_Renderer* renderer;
Expand Down

0 comments on commit 4641bbe

Please sign in to comment.