Skip to content

Commit

Permalink
platform, add resize handling and integer scaling for sdl window mode
Browse files Browse the repository at this point in the history
  • Loading branch information
irixxxx committed Sep 12, 2024
1 parent 7f4bfa9 commit e0a346c
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 50 deletions.
27 changes: 13 additions & 14 deletions platform/common/menu_pico.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ static void make_bg(int no_scale, int from_screen)
int h = g_menubg_src_h ? g_menubg_src_h : g_screen_height;
int pp = g_menubg_src_pp ? g_menubg_src_pp : g_screen_ppitch;
short *dst;
int x, y;

if (from_screen) {
src = g_screen_ptr;
Expand All @@ -104,24 +103,24 @@ static void make_bg(int no_scale, int from_screen)
if (!no_scale && g_menuscreen_w / w >= 2 && g_menuscreen_h / h >= 2)
{
int xf = g_menuscreen_w / w, yf = g_menuscreen_h / h;
int f = no_scale ? 1 : xf < yf ? xf : yf;
int xs = f * w, ys = f * h;
unsigned short t;
int i, j, k, l;
int f = no_scale ? 1 : xf < yf ? xf : yf, xs = f * w, ys = f * h;
int x = (g_menuscreen_w - xs)/2, y = (g_menuscreen_h - ys)/2;
uint16_t *p = (uint16_t *)g_menubg_ptr;
uint16_t *q = (uint16_t *)src;

x = (g_menuscreen_w - xs)/2, y = (g_menuscreen_h - ys)/2;
dst = (short *)g_menubg_ptr + y * g_menuscreen_w + x;
int i, j, k, l;
p += y * g_menuscreen_pp + x;
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++, src++) {
t = (PXMASKH(*src,1)>>1) - (PXMASKH(*src,3)>>3);
for (j = 0; j < w; j++, q++) {
uint16_t t = (PXMASKH(*q,1)>>1) - (PXMASKH(*q,3)>>3);
for (l = 0; l < f; l++)
*dst++ = t;
*p++ = t;
}
src += pp - w;
dst += g_menuscreen_w - xs;
p += g_menuscreen_pp - xs;
q += pp - w;
for (k = 1; k < f; k++) {
memcpy(dst, dst-g_menuscreen_w, g_menuscreen_w*2);
dst += g_menuscreen_w;
memcpy(p, p-g_menuscreen_pp, g_menuscreen_w*2);
p += g_menuscreen_pp;
}
}
return;
Expand Down
131 changes: 95 additions & 36 deletions platform/common/plat_sdl.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,30 @@ void rgb565_to_uyvy(void *d, const void *s, int w, int h, int pitch, int dpitch,
}
}

void copy_intscale(void *dst, int w, int h, int pp, void *src, int sw, int sh, int spp)
{
int xf = w / sw, yf = h / sh;
int f = xf < yf ? xf : yf, xs = f * sw, ys = f * sh;
int x = (w - xs)/2, y = (h - ys)/2;
uint16_t *p = (uint16_t *)dst;
uint16_t *q = (uint16_t *)src;

// copy 16bit image with scaling by an integer factor
int i, j, k, l;
p += y * pp + x;
for (i = 0; i < sh; i++) {
for (j = 0; j < sw; j++, q++)
for (l = 0; l < f; l++)
*p++ = *q;
p += pp - xs;
q += spp - sw;
for (k = 1; k < f; k++) {
memcpy(p, p-pp, w*2);
p += pp;
}
}
}

static int clear_buf_cnt, clear_stat_cnt;

static void resize_buffers(void)
Expand All @@ -188,22 +212,39 @@ static void resize_buffers(void)

void plat_video_set_size(int w, int h)
{
if ((plat_sdl_overlay || plat_sdl_gl_active) &&
(w != g_screen_width || h != g_screen_height)) {
// scale to the window, but mind aspect ratio (scaled to 4:3)
if (g_menuscreen_w * /*h*/w*3/4 >= g_menuscreen_h * w)
w = (w * 3 * g_menuscreen_w/g_menuscreen_h)/4 & ~1;
else
h = (h * 4 * g_menuscreen_h/g_menuscreen_w)/3 & ~1;
}

if (area.w != w || area.h != h) {
area = (struct area) { w, h };
if (plat_sdl_change_video_mode(w, h, 0) < 0) {
// failed, revert to original resolution
area = (struct area) { g_screen_width,g_screen_height };
plat_sdl_change_video_mode(g_screen_width, g_screen_height, 0);

if (plat_sdl_overlay || plat_sdl_gl_active || !plat_sdl_is_windowed()) {
// create surface for overlays, or try using a hw scaler
if (plat_sdl_change_video_mode(w, h, 0) < 0) {
// failed, revert to original resolution
area = (struct area) { g_screen_width,g_screen_height };
plat_sdl_change_video_mode(g_screen_width, g_screen_height, 0);
}
}
if (!plat_sdl_overlay && !plat_sdl_gl_active) {
if (plat_sdl_overlay || plat_sdl_gl_active ||
plat_sdl_screen->w >= 320*2 || plat_sdl_screen->h >= 240*2) {
// use shadow buffer for overlays and sw integer scaling
g_screen_width = area.w;
g_screen_height = area.h;
g_screen_ppitch = area.w;
g_screen_ptr = shadow_fb;
} else {
// unscaled SDL window buffer can be used directly
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_height = h;
g_screen_ppitch = w;
}
}
}
Expand Down Expand Up @@ -236,15 +277,24 @@ void plat_video_flip(void)
gl_flip(shadow_fb, g_screen_ppitch, g_screen_height);
}
else {
if (SDL_MUSTLOCK(plat_sdl_screen)) {
int copy = g_screen_ptr != plat_sdl_screen->pixels;
if (copy)
copy_intscale(plat_sdl_screen->pixels, plat_sdl_screen->w,
plat_sdl_screen->h, plat_sdl_screen->pitch/2,
shadow_fb, area.w, area.h, area.w);

if (SDL_MUSTLOCK(plat_sdl_screen))
SDL_UnlockSurface(plat_sdl_screen);
SDL_Flip(plat_sdl_screen);
SDL_Flip(plat_sdl_screen);
if (SDL_MUSTLOCK(plat_sdl_screen))
SDL_LockSurface(plat_sdl_screen);
} else
SDL_Flip(plat_sdl_screen);
g_screen_ppitch = plat_sdl_screen->pitch/2;
g_screen_ptr = plat_sdl_screen->pixels;
plat_video_set_buffer(g_screen_ptr);

if (!copy) {
g_screen_ppitch = plat_sdl_screen->pitch/2;
g_screen_ptr = plat_sdl_screen->pixels;
plat_video_set_buffer(g_screen_ptr);
}

if (clear_buf_cnt) {
memset(g_screen_ptr, 0, plat_sdl_screen->pitch*plat_sdl_screen->h);
clear_buf_cnt--;
Expand Down Expand Up @@ -277,7 +327,8 @@ void plat_video_clear_status(void)

void plat_video_clear_buffers(void)
{
if (plat_sdl_overlay || plat_sdl_gl_active)
if (plat_sdl_overlay || plat_sdl_gl_active ||
plat_sdl_screen->w >= 320*2 || plat_sdl_screen->h >= 240*2)
memset(shadow_fb, 0, g_menuscreen_w * g_menuscreen_h * 2);
else {
memset(g_screen_ptr, 0, plat_sdl_screen->pitch*plat_sdl_screen->h);
Expand Down Expand Up @@ -366,40 +417,48 @@ void plat_video_loop_prepare(void)
}
g_screen_ppitch = g_screen_width;
g_screen_ptr = shadow_fb;
plat_video_set_size(g_screen_width, g_screen_height);
}
else {
g_screen_width = plat_sdl_screen->w;
g_screen_height = plat_sdl_screen->h;
g_screen_ppitch = plat_sdl_screen->pitch/2;
if (plat_sdl_is_windowed() &&
(plat_sdl_screen->w >= 320*2 || plat_sdl_screen->h >= 240*2)) {
// shadow buffer for integer scaling
g_screen_width = 320;
g_screen_height = 240;
g_screen_ppitch = 320;
g_screen_ptr = shadow_fb;
} else {
// no scaling needed, use screen buffer directly
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;
}
plat_video_set_size(g_screen_width, g_screen_height);

if (SDL_MUSTLOCK(plat_sdl_screen))
SDL_LockSurface(plat_sdl_screen);
g_screen_ptr = plat_sdl_screen->pixels;
}

plat_video_set_size(g_screen_width, g_screen_height);
plat_video_set_buffer(g_screen_ptr);
}

static void plat_sdl_resize(int w, int h)
{
// take over new settings
if (plat_sdl_screen->w != area.w || plat_sdl_screen->h != area.h) {
#if defined(__OPENDINGUX__)
if (currentConfig.vscaling != EOPT_SCALE_HW &&
plat_sdl_screen->w == 320 &&
plat_sdl_screen->h == 480) {
g_menuscreen_h = 240;
g_menuscreen_w = 320;

} else
if (currentConfig.vscaling != EOPT_SCALE_HW &&
plat_sdl_screen->w == 320 && plat_sdl_screen->h == 480) {
g_menuscreen_h = 240;
g_menuscreen_w = 320;
} else
#endif
{
g_menuscreen_h = plat_sdl_screen->h;
g_menuscreen_w = plat_sdl_screen->w;
}
resize_buffers();
rendstatus_old = -1;
{
g_menuscreen_h = plat_sdl_screen->h;
g_menuscreen_w = plat_sdl_screen->w;
}
resize_buffers();
rendstatus_old = -1;
}

static void plat_sdl_quit(void)
Expand Down

0 comments on commit e0a346c

Please sign in to comment.