Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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 3138811
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 14 deletions.
11 changes: 11 additions & 0 deletions include/SDL_hints.h
Expand Up @@ -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
*
Expand Down
65 changes: 51 additions & 14 deletions src/render/SDL_render.c
Expand Up @@ -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;

Expand All @@ -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 */
Expand Down

0 comments on commit 3138811

Please sign in to comment.