platform sdl, preliminary window resizing fixes

picodrive doesn't handle resize events, so it's not really working :-/
it however uncovered some bugs and strange behaviour, though
This commit is contained in:
kub 2022-03-06 18:39:46 +00:00
parent e48f3f2795
commit f8aaa200cf
5 changed files with 95 additions and 35 deletions

View file

@ -84,21 +84,23 @@ int main(int argc, char *argv[])
//in_probe(); //in_probe();
plat_target_init(); plat_target_init();
plat_init();
menu_init();
emu_prep_defconfig(); // depends on input emu_prep_defconfig(); // depends on input
emu_read_config(NULL, 0); emu_read_config(NULL, 0);
plat_init();
menu_init();
emu_init(); emu_init();
engineState = PGS_Menu; engineState = PGS_Menu;
plat_video_menu_enter(0);
if (argc > 1) if (argc > 1)
parse_cmd_line(argc, argv); parse_cmd_line(argc, argv);
if (engineState == PGS_ReloadRom) if (engineState == PGS_ReloadRom)
{ {
plat_video_menu_begin();
if (emu_reload_rom(rom_fname_reload)) { if (emu_reload_rom(rom_fname_reload)) {
engineState = PGS_Running; engineState = PGS_Running;
if (load_state_slot >= 0) { if (load_state_slot >= 0) {
@ -106,7 +108,9 @@ int main(int argc, char *argv[])
emu_save_load_game(1, 0); emu_save_load_game(1, 0);
} }
} }
plat_video_menu_end();
} }
plat_video_menu_leave();
for (;;) for (;;)
{ {

View file

@ -97,10 +97,9 @@ static void make_bg(int no_scale, int from_screen)
pp = g_screen_ppitch; pp = g_screen_ppitch;
} }
if (src == NULL) { memset(g_menubg_ptr, 0, g_menuscreen_w * g_menuscreen_h * 2);
memset(g_menubg_ptr, 0, g_menuscreen_w * g_menuscreen_h * 2); if (src == NULL)
return; return;
}
if (!no_scale && g_menuscreen_w / w >= 2 && g_menuscreen_h / h >= 2) if (!no_scale && g_menuscreen_w / w >= 2 && g_menuscreen_h / h >= 2)
{ {

View file

@ -1,6 +1,7 @@
/* /*
* PicoDrive * PicoDrive
* (C) notaz, 2013 * (C) notaz, 2013
* (C) kub, 2020-2022
* *
* This work is licensed under the terms of MAME license. * This work is licensed under the terms of MAME license.
* See COPYING file in the top-level directory. * See COPYING file in the top-level directory.
@ -22,6 +23,7 @@
#include <pico/pico_int.h> #include <pico/pico_int.h>
static void *shadow_fb; static void *shadow_fb;
static int shadow_size;
static struct area { int w, h; } area; static struct area { int w, h; } area;
static struct in_pdata in_sdl_platform_data = { static struct in_pdata in_sdl_platform_data = {
@ -82,14 +84,14 @@ void bgr_to_uyvy_init(void)
} }
} }
void rgb565_to_uyvy(void *d, const void *s, int w, int h, int pitch, int x2) void rgb565_to_uyvy(void *d, const void *s, int w, int h, int pitch, int dpitch, int x2)
{ {
uint32_t *dst = d; uint32_t *dst = d;
const uint16_t *src = s; const uint16_t *src = s;
int i; int i;
if (x2) while (h--) { if (x2) while (h--) {
for (i = w; i > 0; src += 4, dst += 4, i -= 4) for (i = w; i >= 4; src += 4, dst += 4, i -= 4)
{ {
struct uyvy *uyvy0 = yuv_uyvy + src[0], *uyvy1 = yuv_uyvy + src[1]; struct uyvy *uyvy0 = yuv_uyvy + src[0], *uyvy1 = yuv_uyvy + src[1];
struct uyvy *uyvy2 = yuv_uyvy + src[2], *uyvy3 = yuv_uyvy + src[3]; struct uyvy *uyvy2 = yuv_uyvy + src[2], *uyvy3 = yuv_uyvy + src[3];
@ -105,9 +107,10 @@ void rgb565_to_uyvy(void *d, const void *s, int w, int h, int pitch, int x2)
dst[3] = uyvy3->y | (uyvy3->vyu << 8); dst[3] = uyvy3->y | (uyvy3->vyu << 8);
#endif #endif
} }
src += pitch - w; src += pitch - (w-i);
dst += (dpitch - 2*(w-i))/2;
} else while (h--) { } else while (h--) {
for (i = w; i > 0; src += 4, dst += 2, i -= 4) for (i = w; i >= 4; src += 4, dst += 2, i -= 4)
{ {
struct uyvy *uyvy0 = yuv_uyvy + src[0], *uyvy1 = yuv_uyvy + src[1]; struct uyvy *uyvy0 = yuv_uyvy + src[0], *uyvy1 = yuv_uyvy + src[1];
struct uyvy *uyvy2 = yuv_uyvy + src[2], *uyvy3 = yuv_uyvy + src[3]; struct uyvy *uyvy2 = yuv_uyvy + src[2], *uyvy3 = yuv_uyvy + src[3];
@ -119,12 +122,23 @@ void rgb565_to_uyvy(void *d, const void *s, int w, int h, int pitch, int x2)
dst[1] = uyvy3->y | (uyvy2->vyu << 8); dst[1] = uyvy3->y | (uyvy2->vyu << 8);
#endif #endif
} }
src += pitch - w; src += pitch - (w-i);
dst += (dpitch - (w-i))/2;
} }
} }
static int clear_buf_cnt, clear_stat_cnt; static int clear_buf_cnt, clear_stat_cnt;
static void resize_buffers(void)
{
// make sure the shadow buffers are big enough in case of resize
if (shadow_size < g_menuscreen_w * g_menuscreen_h * 2) {
shadow_size = g_menuscreen_w * g_menuscreen_h * 2;
shadow_fb = realloc(shadow_fb, shadow_size);
g_menubg_ptr = realloc(g_menubg_ptr, shadow_size);
}
}
void plat_video_set_size(int w, int h) void plat_video_set_size(int w, int h)
{ {
if (area.w != w || area.h != h) { if (area.w != w || area.h != h) {
@ -134,10 +148,14 @@ void plat_video_set_size(int w, int h)
w = g_screen_width, h = g_screen_height; w = g_screen_width, h = g_screen_height;
} }
if (!plat_sdl_overlay && !plat_sdl_gl_active) { if (!plat_sdl_overlay && !plat_sdl_gl_active) {
g_screen_width = plat_sdl_screen->w;
g_screen_height = plat_sdl_screen->h;
g_screen_ppitch = plat_sdl_screen->pitch/2;
g_screen_ptr = plat_sdl_screen->pixels;
} else {
g_screen_width = w; g_screen_width = w;
g_screen_height = h; g_screen_height = h;
g_screen_ppitch = w; g_screen_ppitch = w;
g_screen_ptr = plat_sdl_screen->pixels;
} }
area = (struct area) { w, h }; area = (struct area) { w, h };
} }
@ -145,13 +163,17 @@ void plat_video_set_size(int w, int h)
void plat_video_flip(void) void plat_video_flip(void)
{ {
resize_buffers();
if (plat_sdl_overlay != NULL) { if (plat_sdl_overlay != NULL) {
SDL_Rect dstrect = SDL_Rect dstrect =
{ 0, 0, plat_sdl_screen->w, plat_sdl_screen->h }; { 0, 0, plat_sdl_screen->w, plat_sdl_screen->h };
SDL_LockYUVOverlay(plat_sdl_overlay); SDL_LockYUVOverlay(plat_sdl_overlay);
rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb, if (area.w <= plat_sdl_overlay->w && area.h <= plat_sdl_overlay->h)
area.w, area.h, g_screen_ppitch, rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb,
plat_sdl_overlay->w >= 2*area.w); area.w, area.h, g_screen_ppitch,
plat_sdl_overlay->pitches[0]/2,
plat_sdl_overlay->w >= 2*area.w);
SDL_UnlockYUVOverlay(plat_sdl_overlay); SDL_UnlockYUVOverlay(plat_sdl_overlay);
SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect); SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
} }
@ -165,6 +187,7 @@ void plat_video_flip(void)
SDL_LockSurface(plat_sdl_screen); SDL_LockSurface(plat_sdl_screen);
} else } else
SDL_Flip(plat_sdl_screen); SDL_Flip(plat_sdl_screen);
g_screen_ppitch = plat_sdl_screen->pitch/2;
g_screen_ptr = plat_sdl_screen->pixels; g_screen_ptr = plat_sdl_screen->pixels;
plat_video_set_buffer(g_screen_ptr); plat_video_set_buffer(g_screen_ptr);
if (clear_buf_cnt) { if (clear_buf_cnt) {
@ -172,6 +195,14 @@ void plat_video_flip(void)
clear_buf_cnt--; clear_buf_cnt--;
} }
} }
// for overlay/gl modes buffer ptr may change on resize
if ((plat_sdl_overlay || plat_sdl_gl_active) &&
(g_screen_ptr != shadow_fb || g_screen_ppitch != g_screen_width)) {
g_screen_ppitch = g_screen_width;
g_screen_ptr = shadow_fb;
plat_video_set_buffer(g_screen_ptr);
}
if (clear_stat_cnt) { if (clear_stat_cnt) {
unsigned short *d = (unsigned short *)g_screen_ptr + g_screen_ppitch * g_screen_height; unsigned short *d = (unsigned short *)g_screen_ptr + g_screen_ppitch * g_screen_height;
int l = g_screen_ppitch * 8; int l = g_screen_ppitch * 8;
@ -191,7 +222,7 @@ void plat_video_clear_status(void)
void plat_video_clear_buffers(void) void plat_video_clear_buffers(void)
{ {
if (plat_sdl_overlay != NULL || plat_sdl_gl_active) if (plat_sdl_overlay || plat_sdl_gl_active)
memset(shadow_fb, 0, g_menuscreen_w * g_menuscreen_h * 2); memset(shadow_fb, 0, g_menuscreen_w * g_menuscreen_h * 2);
else { else {
memset(g_screen_ptr, 0, plat_sdl_screen->w*plat_sdl_screen->h * 2); memset(g_screen_ptr, 0, plat_sdl_screen->w*plat_sdl_screen->h * 2);
@ -204,18 +235,20 @@ void plat_video_menu_enter(int is_rom_loaded)
if (SDL_MUSTLOCK(plat_sdl_screen)) if (SDL_MUSTLOCK(plat_sdl_screen))
SDL_UnlockSurface(plat_sdl_screen); SDL_UnlockSurface(plat_sdl_screen);
plat_sdl_change_video_mode(g_menuscreen_w, g_menuscreen_h, 1); plat_sdl_change_video_mode(g_menuscreen_w, g_menuscreen_h, 1);
g_screen_ptr = shadow_fb; resize_buffers();
plat_video_set_buffer(g_screen_ptr);
} }
void plat_video_menu_begin(void) void plat_video_menu_begin(void)
{ {
if (plat_sdl_overlay != NULL || plat_sdl_gl_active) { resize_buffers();
if (plat_sdl_overlay || plat_sdl_gl_active) {
g_menuscreen_pp = g_menuscreen_w;
g_menuscreen_ptr = shadow_fb; g_menuscreen_ptr = shadow_fb;
} }
else { else {
if (SDL_MUSTLOCK(plat_sdl_screen)) if (SDL_MUSTLOCK(plat_sdl_screen))
SDL_LockSurface(plat_sdl_screen); SDL_LockSurface(plat_sdl_screen);
g_menuscreen_pp = plat_sdl_screen->pitch / 2;
g_menuscreen_ptr = plat_sdl_screen->pixels; g_menuscreen_ptr = plat_sdl_screen->pixels;
} }
} }
@ -227,8 +260,11 @@ void plat_video_menu_end(void)
{ 0, 0, plat_sdl_screen->w, plat_sdl_screen->h }; { 0, 0, plat_sdl_screen->w, plat_sdl_screen->h };
SDL_LockYUVOverlay(plat_sdl_overlay); SDL_LockYUVOverlay(plat_sdl_overlay);
rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb, if (g_menuscreen_w <= plat_sdl_overlay->w && g_menuscreen_h <= plat_sdl_overlay->h)
g_menuscreen_w, g_menuscreen_h, g_menuscreen_pp, 0); rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb,
g_menuscreen_w, g_menuscreen_h, g_menuscreen_pp,
plat_sdl_overlay->pitches[0]/2,
plat_sdl_overlay->w >= 2 * g_menuscreen_w);
SDL_UnlockYUVOverlay(plat_sdl_overlay); SDL_UnlockYUVOverlay(plat_sdl_overlay);
SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect); SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
@ -251,31 +287,43 @@ void plat_video_menu_leave(void)
void plat_video_loop_prepare(void) void plat_video_loop_prepare(void)
{ {
// take over any new vout settings // take over any new vout settings
plat_sdl_change_video_mode(g_menuscreen_w, g_menuscreen_h, 0); plat_sdl_change_video_mode(0, 0, 0);
area.w = g_menuscreen_w, area.h = g_menuscreen_h;
resize_buffers();
// switch over to scaled output if available, but keep the aspect ratio // switch over to scaled output if available, but keep the aspect ratio
if (plat_sdl_overlay != NULL || plat_sdl_gl_active) { if (plat_sdl_overlay || plat_sdl_gl_active) {
g_screen_width = (240 * g_menuscreen_w / g_menuscreen_h) & ~1; g_screen_width = (240 * g_menuscreen_w / g_menuscreen_h) & ~1;
g_screen_height = 240; g_screen_height = 240;
g_screen_ppitch = g_screen_width; g_screen_ppitch = g_screen_width;
plat_sdl_change_video_mode(g_screen_width, g_screen_height, 0);
g_screen_ptr = shadow_fb; g_screen_ptr = shadow_fb;
} }
else { else {
g_screen_width = g_menuscreen_w; g_screen_width = plat_sdl_screen->w;
g_screen_height = g_menuscreen_h; g_screen_height = plat_sdl_screen->h;
g_screen_ppitch = g_menuscreen_pp; g_screen_ppitch = plat_sdl_screen->pitch/2;
if (SDL_MUSTLOCK(plat_sdl_screen)) if (SDL_MUSTLOCK(plat_sdl_screen))
SDL_LockSurface(plat_sdl_screen); SDL_LockSurface(plat_sdl_screen);
g_screen_ptr = plat_sdl_screen->pixels; g_screen_ptr = plat_sdl_screen->pixels;
} }
plat_video_set_buffer(g_screen_ptr);
plat_video_set_size(g_screen_width, g_screen_height); plat_video_set_size(g_screen_width, g_screen_height);
plat_video_set_buffer(g_screen_ptr);
} }
void plat_early_init(void) void plat_early_init(void)
{ {
} }
static void plat_sdl_resize(int w, int h)
{
// take over new settings
g_menuscreen_h = (plat_sdl_screen->h < 480 ? plat_sdl_screen->h : 480);
if (!plat_sdl_overlay && !plat_sdl_gl_active)
g_menuscreen_h = plat_sdl_screen->h;
g_menuscreen_w = g_menuscreen_h * plat_sdl_screen->w/plat_sdl_screen->h;
}
static void plat_sdl_quit(void) static void plat_sdl_quit(void)
{ {
// for now.. // for now..
@ -284,24 +332,22 @@ static void plat_sdl_quit(void)
void plat_init(void) void plat_init(void)
{ {
int shadow_size;
int ret; int ret;
ret = plat_sdl_init(); ret = plat_sdl_init();
if (ret != 0) if (ret != 0)
exit(1); exit(1);
SDL_ShowCursor(0);
#if defined(__RG350__) || defined(__GCW0__) || defined(__OPENDINGUX__) #if defined(__RG350__) || defined(__GCW0__) || defined(__OPENDINGUX__)
// opendingux on JZ47x0 may falsely report a HW overlay, fix to window // opendingux on JZ47x0 may falsely report a HW overlay, fix to window
plat_target.vout_method = 0; plat_target.vout_method = 0;
#endif #endif
plat_sdl_quit_cb = plat_sdl_quit; plat_sdl_quit_cb = plat_sdl_quit;
plat_sdl_resize_cb = plat_sdl_resize;
SDL_ShowCursor(0);
SDL_WM_SetCaption("PicoDrive " VERSION, NULL); SDL_WM_SetCaption("PicoDrive " VERSION, NULL);
g_menuscreen_w = plat_sdl_screen->w;
g_menuscreen_h = plat_sdl_screen->h;
g_menuscreen_pp = g_menuscreen_w; g_menuscreen_pp = g_menuscreen_w;
g_menuscreen_ptr = NULL; g_menuscreen_ptr = NULL;

@ -1 +1 @@
Subproject commit 81b1aa54a4d31f43f8f6d72c95a7898b2a871791 Subproject commit e3ea3015f042cb3a1615dc3038b524ce0a063722

View file

@ -297,7 +297,6 @@ void pemu_forced_frame(int no_scale, int do_emu)
Pico.m.dirtyPal = 1; Pico.m.dirtyPal = 1;
if (currentConfig.scaling) currentConfig.scaling = EOPT_SCALE_SW; if (currentConfig.scaling) currentConfig.scaling = EOPT_SCALE_SW;
if (currentConfig.vscaling) currentConfig.vscaling = EOPT_SCALE_SW; if (currentConfig.vscaling) currentConfig.vscaling = EOPT_SCALE_SW;
plat_video_set_size(g_menuscreen_w, g_menuscreen_h);
// render a frame in 16 bit mode // render a frame in 16 bit mode
render_bg = 1; render_bg = 1;
@ -402,10 +401,18 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co
break; break;
} }
if (screen_w != g_screen_width || screen_h != g_screen_height) plat_video_set_size(screen_w, screen_h);
plat_video_set_size(screen_w, screen_h);
plat_video_set_buffer(g_screen_ptr); plat_video_set_buffer(g_screen_ptr);
if (screen_w < g_screen_width)
screen_x = (g_screen_width - screen_w)/2;
if (screen_h < g_screen_height) {
screen_y = (g_screen_height - screen_h)/2;
// NTSC always has 224 visible lines, anything smaller has bars
if (out_h < 224 && out_h > 144)
screen_y += (224 - out_h)/2;
}
// create a backing buffer for emulating the bad GG lcd display // create a backing buffer for emulating the bad GG lcd display
if (currentConfig.ghosting && out_h == 144) { if (currentConfig.ghosting && out_h == 144) {
int h = currentConfig.vscaling == EOPT_SCALE_SW ? 240:out_h; int h = currentConfig.vscaling == EOPT_SCALE_SW ? 240:out_h;
@ -429,7 +436,11 @@ void pemu_loop_prep(void)
void pemu_loop_end(void) void pemu_loop_end(void)
{ {
/* do one more frame for menu bg */ /* do one more frame for menu bg */
plat_video_set_size(320, 240);
pemu_forced_frame(0, 1); pemu_forced_frame(0, 1);
g_menubg_src_w = g_screen_width;
g_menubg_src_h = g_screen_height;
g_menubg_src_pp = g_screen_ppitch;
if (ghost_buf) { if (ghost_buf) {
free(ghost_buf); free(ghost_buf);
ghost_buf = NULL; ghost_buf = NULL;