From 05b71ace4f2669b253ac62fd9bedee40fb4c32f2 Mon Sep 17 00:00:00 2001 From: Cpasjuste Date: Wed, 28 Mar 2018 00:17:08 +0200 Subject: [PATCH] switch: handle aspect ratio correction in fullscreen mode --- src/video/switch/SDL_switchvideo.c | 27 ++++++++++++++------- test/testswitch.c | 39 +++++++++++++++--------------- 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/video/switch/SDL_switchvideo.c b/src/video/switch/SDL_switchvideo.c index aee219b3b..86091afd4 100644 --- a/src/video/switch/SDL_switchvideo.c +++ b/src/video/switch/SDL_switchvideo.c @@ -37,6 +37,7 @@ typedef struct { SDL_Surface *surface; + int x_offset; } SWITCH_WindowData; static int SWITCH_VideoInit(_THIS); @@ -157,23 +158,31 @@ static int SWITCH_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *for return -1; } - // hold a pointer to our surface + // hold a pointer to our stuff data = SDL_calloc(1, sizeof(SWITCH_WindowData)); data->surface = surface; - SDL_SetWindowData(window, SWITCH_DATA, data); // use switch hardware scaling in fullscreen mode 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 { gfxConfigureResolution(0, 0); + data->x_offset = 0; } *format = SDL_PIXELFORMAT_ABGR8888; *pixels = surface->pixels; *pitch = surface->pitch; + SDL_SetWindowData(window, SWITCH_DATA, data); + // inform SDL we're ready to accept inputs 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 *dst = (u32 *) gfxGetFramebuffer(&fb_w, &fb_h); - // prevent framebuffer overflow in case of resolution change outside SDL, - // which should not happen - if(window->x + w > fb_w) { + // prevent fb overflow in case of resolution change outside SDL + if (window->x + w > fb_w) { w = fb_w - window->x; } - if(window->y + h > fb_h) { + if (window->y + h > fb_h) { h = fb_h - window->y; } for (y = 0; y < h; y++) { 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]); } } gfxFlushBuffers(); gfxSwapBuffers(); - // TODO: handle SDL_RENDERER_PRESENTVSYNC (SW_RenderDriver not using flags) + // TODO: handle SDL_RENDERER_PRESENTVSYNC (SW_RenderDriver not accepting flags) gfxWaitForVsync(); return 0; diff --git a/test/testswitch.c b/test/testswitch.c index 6429ccdbf..4c1613d40 100644 --- a/test/testswitch.c +++ b/test/testswitch.c @@ -34,10 +34,11 @@ int main(int argc, char *argv[]) return -1; } - // create a 800x600 centered window for demonstration. - // if SDL_WINDOW_FULLSCREEN flag is passed, the window will be hardware scaled to fit switch screen. + // create a 800x600 window for demonstration. + // 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 - 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) { printf("SDL_CreateWindow: %s\n", SDL_GetError()); SDL_Quit(); @@ -70,24 +71,24 @@ int main(int argc, char *argv[]) switch (event.type) { - case SDL_JOYAXISMOTION: - printf("Joystick %d axis %d value: %d\n", - event.jaxis.which, - event.jaxis.axis, event.jaxis.value); - break; + case SDL_JOYAXISMOTION: + printf("Joystick %d axis %d value: %d\n", + event.jaxis.which, + event.jaxis.axis, event.jaxis.value); + break; - case SDL_JOYBUTTONDOWN: - printf("Joystick %d button %d down\n", - event.jbutton.which, event.jbutton.button); - // seek for joystick #0 down (B) - // https://github.com/devkitPro/SDL/blob/switch-sdl2/src/joystick/switch/SDL_sysjoystick.c#L51 - if (event.jbutton.which == 0 && event.jbutton.button == 1) { - done = 1; - } - break; + case SDL_JOYBUTTONDOWN: + printf("Joystick %d button %d down\n", + event.jbutton.which, event.jbutton.button); + // seek for joystick #0 down (B) + // https://github.com/devkitPro/SDL/blob/switch-sdl2/src/joystick/switch/SDL_sysjoystick.c#L51 + if (event.jbutton.which == 0 && event.jbutton.button == 1) { + done = 1; + } + break; - default: - break; + default: + break; } }