switch: handle aspect ratio correction in fullscreen mode

This commit is contained in:
Cpasjuste 2018-03-28 00:17:08 +02:00 committed by Dave Murphy
parent 53e19d42b9
commit 05b71ace4f
2 changed files with 38 additions and 28 deletions

View File

@ -37,6 +37,7 @@
typedef struct typedef struct
{ {
SDL_Surface *surface; SDL_Surface *surface;
int x_offset;
} SWITCH_WindowData; } SWITCH_WindowData;
static int SWITCH_VideoInit(_THIS); static int SWITCH_VideoInit(_THIS);
@ -157,23 +158,31 @@ static int SWITCH_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *for
return -1; return -1;
} }
// hold a pointer to our surface // hold a pointer to our stuff
data = SDL_calloc(1, sizeof(SWITCH_WindowData)); data = SDL_calloc(1, sizeof(SWITCH_WindowData));
data->surface = surface; data->surface = surface;
SDL_SetWindowData(window, SWITCH_DATA, data);
// use switch hardware scaling in fullscreen mode // use switch hardware scaling in fullscreen mode
if (window->flags & SDL_WINDOW_FULLSCREEN) { if (window->flags & SDL_WINDOW_FULLSCREEN) {
gfxConfigureResolution(window->w, window->h); float scaling = (float) window->h / (float) SCREEN_HEIGHT;
float w = SDL_min(SCREEN_WIDTH, SCREEN_WIDTH * scaling);
// calculate x offset, to respect aspect ratio
// round down to multiple of 4 for faster fb writes
int offset = (int) (w - (window->w)) / 2;
data->x_offset = offset & ~3;
gfxConfigureResolution((int) w, window->h);
} }
else { else {
gfxConfigureResolution(0, 0); gfxConfigureResolution(0, 0);
data->x_offset = 0;
} }
*format = SDL_PIXELFORMAT_ABGR8888; *format = SDL_PIXELFORMAT_ABGR8888;
*pixels = surface->pixels; *pixels = surface->pixels;
*pitch = surface->pitch; *pitch = surface->pitch;
SDL_SetWindowData(window, SWITCH_DATA, data);
// inform SDL we're ready to accept inputs // inform SDL we're ready to accept inputs
SDL_SetKeyboardFocus(window); SDL_SetKeyboardFocus(window);
@ -189,25 +198,25 @@ static int SWITCH_UpdateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_R
u32 *src = (u32 *) data->surface->pixels; u32 *src = (u32 *) data->surface->pixels;
u32 *dst = (u32 *) gfxGetFramebuffer(&fb_w, &fb_h); u32 *dst = (u32 *) gfxGetFramebuffer(&fb_w, &fb_h);
// prevent framebuffer overflow in case of resolution change outside SDL, // prevent fb overflow in case of resolution change outside SDL
// which should not happen if (window->x + w > fb_w) {
if(window->x + w > fb_w) {
w = fb_w - window->x; w = fb_w - window->x;
} }
if(window->y + h > fb_h) { if (window->y + h > fb_h) {
h = fb_h - window->y; h = fb_h - window->y;
} }
for (y = 0; y < h; y++) { for (y = 0; y < h; y++) {
for (x = 0; x < w; x += 4) { for (x = 0; x < w; x += 4) {
*((u128 *) &dst[gfxGetFramebufferDisplayOffset((u32) (x + window->x), (u32) (y + window->y))]) = *((u128 *) &dst[gfxGetFramebufferDisplayOffset(
(u32) (x + window->x + data->x_offset), (u32) (y + window->y))]) =
*((u128 *) &src[y * w + x]); *((u128 *) &src[y * w + x]);
} }
} }
gfxFlushBuffers(); gfxFlushBuffers();
gfxSwapBuffers(); gfxSwapBuffers();
// TODO: handle SDL_RENDERER_PRESENTVSYNC (SW_RenderDriver not using flags) // TODO: handle SDL_RENDERER_PRESENTVSYNC (SW_RenderDriver not accepting flags)
gfxWaitForVsync(); gfxWaitForVsync();
return 0; return 0;

View File

@ -34,10 +34,11 @@ int main(int argc, char *argv[])
return -1; return -1;
} }
// create a 800x600 centered window for demonstration. // create a 800x600 window for demonstration.
// if SDL_WINDOW_FULLSCREEN flag is passed, the window will be hardware scaled to fit switch screen. // if SDL_WINDOW_FULLSCREEN flag is passed, it will be hardware scaled (stretched) to fit screen,
// will always be centered and aspect ratio maintained.
// maximum window dimension is currently limited to 1280x720 // maximum window dimension is currently limited to 1280x720
window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, 0); window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_FULLSCREEN);
if (!window) { if (!window) {
printf("SDL_CreateWindow: %s\n", SDL_GetError()); printf("SDL_CreateWindow: %s\n", SDL_GetError());
SDL_Quit(); SDL_Quit();
@ -70,24 +71,24 @@ int main(int argc, char *argv[])
switch (event.type) { switch (event.type) {
case SDL_JOYAXISMOTION: case SDL_JOYAXISMOTION:
printf("Joystick %d axis %d value: %d\n", printf("Joystick %d axis %d value: %d\n",
event.jaxis.which, event.jaxis.which,
event.jaxis.axis, event.jaxis.value); event.jaxis.axis, event.jaxis.value);
break; break;
case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONDOWN:
printf("Joystick %d button %d down\n", printf("Joystick %d button %d down\n",
event.jbutton.which, event.jbutton.button); event.jbutton.which, event.jbutton.button);
// seek for joystick #0 down (B) // seek for joystick #0 down (B)
// https://github.com/devkitPro/SDL/blob/switch-sdl2/src/joystick/switch/SDL_sysjoystick.c#L51 // https://github.com/devkitPro/SDL/blob/switch-sdl2/src/joystick/switch/SDL_sysjoystick.c#L51
if (event.jbutton.which == 0 && event.jbutton.button == 1) { if (event.jbutton.which == 0 && event.jbutton.button == 1) {
done = 1; done = 1;
} }
break; break;
default: default:
break; break;
} }
} }