Skip to content
Permalink
Browse files

Adds support to control the scaling policy/mode of SDL_RenderSetLogic…

…alSize for both letterbox (current behavior) and a new overscan mode (expand to fill the entire screen, even if some parts draw off the screen).

The expected use case is for games that are designed with multiple aspect ratios already in mind and leave optional margins on the edges of the game which won't hurt if they are cut off.

An example use case is a game is designed for wide-screen/16:9, but then wants to deploy on an iPad which is 4:3. Normally, SDL will letterbox, which will shrink things and result in wasted space. But the designer already thought about 4:3 and designed the edges of the game so they could be cut off without any functional loss. So rather than wasting space with letterboxing, "overscan" mode will zoom the rendering to fill up the entire screen. Parts on the edges will be drawn offscreen, but since the game was already designed with this in mind, it is fine. The end result is the iPad (4:3) experience is much better since it feels like a game designed for that screen aspect ratio.

This patch introduces a new SDL_hint: SDL_HINT_RENDER_LOGICAL_SIZE_MODE.
Valid values are "letterbox" or "0" for letterboxing and "overscan" or "1" for overscan.
The default mode is letterbox to preserve existing behavior.

// Example usage:
SDL_SetHint(SDL_HINT_RENDER_LOGICAL_SIZE_MODE, "overscan");
SDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT);
  • Loading branch information
Eric Wing committed Dec 3, 2014
1 parent 5fee84f commit 313881175dca4a27cd0fcde02d9f5eb88d42c38a
Showing with 62 additions and 14 deletions.
  1. +11 −0 include/SDL_hints.h
  2. +51 −14 src/render/SDL_render.c
@@ -118,6 +118,17 @@ extern "C" {
*/
#define SDL_HINT_RENDER_DIRECT3D11_DEBUG "SDL_RENDER_DIRECT3D11_DEBUG"

/**
* \brief A variable controlling the scaling policy for SDL_RenderSetLogicalSize.
*
* This variable can be set to the following values:
* "0" or "letterbox" - Uses letterbox/sidebars to fit the entire rendering on screen
* "1" or "overscan" - Will zoom the rendering so it fills the entire screen, allowing edges to be drawn offscreen
*
* By default letterbox is used
*/
#define SDL_HINT_RENDER_LOGICAL_SIZE_MODE "SDL_HINT_RENDER_LOGICAL_SIZE_MODE"

/**
* \brief A variable controlling the scaling quality
*
@@ -1138,11 +1138,22 @@ UpdateLogicalSize(SDL_Renderer *renderer)
float real_aspect;
float scale;
SDL_Rect viewport;
/* 0 is for letterbox, 1 is for overscan */
int scale_policy = 0;
const char *hint = SDL_GetHint(SDL_HINT_RENDER_LOGICAL_SIZE_MODE);

if (SDL_GetRendererOutputSize(renderer, &w, &h) < 0) {
return -1;
}

if (!hint) {
scale_policy = 0;
} else if ( *hint == '1' || SDL_strcasecmp(hint, "overscan") == 0) {
scale_policy = 1;
} else {
scale_policy = 0;
}

want_aspect = (float)renderer->logical_w / renderer->logical_h;
real_aspect = (float)w / h;

@@ -1154,21 +1165,47 @@ UpdateLogicalSize(SDL_Renderer *renderer)
scale = (float)w / renderer->logical_w;
SDL_RenderSetViewport(renderer, NULL);
} else if (want_aspect > real_aspect) {
/* We want a wider aspect ratio than is available - letterbox it */
scale = (float)w / renderer->logical_w;
viewport.x = 0;
viewport.w = w;
viewport.h = (int)SDL_ceil(renderer->logical_h * scale);
viewport.y = (h - viewport.h) / 2;
SDL_RenderSetViewport(renderer, &viewport);
if (scale_policy == 1) {
/* We want a wider aspect ratio than is available -
zoom so logical height matches the real height
and the width will grow off the screen
*/
scale = (float)h / renderer->logical_h;
viewport.y = 0;
viewport.h = h;
viewport.w = (int)SDL_ceil(renderer->logical_w * scale);
viewport.x = (w - viewport.w) / 2;
SDL_RenderSetViewport(renderer, &viewport);
} else {
/* We want a wider aspect ratio than is available - letterbox it */
scale = (float)w / renderer->logical_w;
viewport.x = 0;
viewport.w = w;
viewport.h = (int)SDL_ceil(renderer->logical_h * scale);
viewport.y = (h - viewport.h) / 2;
SDL_RenderSetViewport(renderer, &viewport);
}
} else {
/* We want a narrower aspect ratio than is available - use side-bars */
scale = (float)h / renderer->logical_h;
viewport.y = 0;
viewport.h = h;
viewport.w = (int)SDL_ceil(renderer->logical_w * scale);
viewport.x = (w - viewport.w) / 2;
SDL_RenderSetViewport(renderer, &viewport);
if (scale_policy == 1) {
/* We want a narrower aspect ratio than is available -
zoom so logical width matches the real width
and the height will grow off the screen
*/
scale = (float)w / renderer->logical_w;
viewport.x = 0;
viewport.w = w;
viewport.h = (int)SDL_ceil(renderer->logical_h * scale);
viewport.y = (h - viewport.h) / 2;
SDL_RenderSetViewport(renderer, &viewport);
} else {
/* We want a narrower aspect ratio than is available - use side-bars */
scale = (float)h / renderer->logical_h;
viewport.y = 0;
viewport.h = h;
viewport.w = (int)SDL_ceil(renderer->logical_w * scale);
viewport.x = (w - viewport.w) / 2;
SDL_RenderSetViewport(renderer, &viewport);
}
}

/* Set the new scale */

0 comments on commit 3138811

Please sign in to comment.