sdl, complete overhaul of hardware/software scaling

This commit is contained in:
kub 2021-09-10 18:46:05 +02:00
parent 6651998e9f
commit d5d1778252
21 changed files with 1233 additions and 547 deletions

View file

@ -22,6 +22,7 @@
#include <pico/pico_int.h>
static void *shadow_fb;
static struct area { int w, h; } area;
static struct in_pdata in_sdl_platform_data = {
.defbinds = in_sdl_defbinds,
@ -81,54 +82,77 @@ void bgr_to_uyvy_init(void)
}
}
void rgb565_to_uyvy(void *d, const void *s, int pixels, int x2)
void rgb565_to_uyvy(void *d, const void *s, int w, int h, int pitch, int x2)
{
uint32_t *dst = d;
const uint16_t *src = s;
int i;
if (x2)
for (; pixels > 0; src += 4, dst += 4, pixels -= 4)
{
struct uyvy *uyvy0 = yuv_uyvy + src[0], *uyvy1 = yuv_uyvy + src[1];
struct uyvy *uyvy2 = yuv_uyvy + src[2], *uyvy3 = yuv_uyvy + src[3];
if (x2) while (h--) {
for (i = w; i > 0; src += 4, dst += 4, i -= 4)
{
struct uyvy *uyvy0 = yuv_uyvy + src[0], *uyvy1 = yuv_uyvy + src[1];
struct uyvy *uyvy2 = yuv_uyvy + src[2], *uyvy3 = yuv_uyvy + src[3];
#if CPU_IS_LE
dst[0] = (uyvy0->y << 24) | uyvy0->vyu;
dst[1] = (uyvy1->y << 24) | uyvy1->vyu;
dst[2] = (uyvy2->y << 24) | uyvy2->vyu;
dst[3] = (uyvy3->y << 24) | uyvy3->vyu;
dst[0] = (uyvy0->y << 24) | uyvy0->vyu;
dst[1] = (uyvy1->y << 24) | uyvy1->vyu;
dst[2] = (uyvy2->y << 24) | uyvy2->vyu;
dst[3] = (uyvy3->y << 24) | uyvy3->vyu;
#else
dst[0] = uyvy0->y | (uyvy0->vyu << 8);
dst[1] = uyvy1->y | (uyvy1->vyu << 8);
dst[2] = uyvy2->y | (uyvy2->vyu << 8);
dst[3] = uyvy3->y | (uyvy3->vyu << 8);
dst[0] = uyvy0->y | (uyvy0->vyu << 8);
dst[1] = uyvy1->y | (uyvy1->vyu << 8);
dst[2] = uyvy2->y | (uyvy2->vyu << 8);
dst[3] = uyvy3->y | (uyvy3->vyu << 8);
#endif
} else
for (; pixels > 0; src += 4, dst += 2, pixels -= 4)
{
struct uyvy *uyvy0 = yuv_uyvy + src[0], *uyvy1 = yuv_uyvy + src[1];
struct uyvy *uyvy2 = yuv_uyvy + src[2], *uyvy3 = yuv_uyvy + src[3];
}
src += pitch - w;
} else while (h--) {
for (i = w; i > 0; src += 4, dst += 2, i -= 4)
{
struct uyvy *uyvy0 = yuv_uyvy + src[0], *uyvy1 = yuv_uyvy + src[1];
struct uyvy *uyvy2 = yuv_uyvy + src[2], *uyvy3 = yuv_uyvy + src[3];
#if CPU_IS_LE
dst[0] = (uyvy1->y << 24) | uyvy0->vyu;
dst[1] = (uyvy3->y << 24) | uyvy2->vyu;
dst[0] = (uyvy1->y << 24) | uyvy0->vyu;
dst[1] = (uyvy3->y << 24) | uyvy2->vyu;
#else
dst[0] = uyvy1->y | (uyvy0->vyu << 8);
dst[1] = uyvy3->y | (uyvy2->vyu << 8);
dst[0] = uyvy1->y | (uyvy0->vyu << 8);
dst[1] = uyvy3->y | (uyvy2->vyu << 8);
#endif
}
src += pitch - w;
}
}
static int clear_buf_cnt, clear_stat_cnt;
void plat_video_set_size(int w, int h)
{
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
plat_sdl_change_video_mode(g_screen_width, g_screen_height, 0);
w = g_screen_width, h = g_screen_height;
}
if (!plat_sdl_overlay && !plat_sdl_gl_active) {
g_screen_width = w;
g_screen_height = h;
g_screen_ppitch = w;
g_screen_ptr = plat_sdl_screen->pixels;
}
}
}
void plat_video_flip(void)
{
if (plat_sdl_overlay != NULL) {
SDL_Rect dstrect =
{ 0, 0, plat_sdl_screen->w, plat_sdl_screen->h };
SDL_LockYUVOverlay(plat_sdl_overlay);
rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb,
g_screen_ppitch * g_screen_height,
plat_sdl_overlay->w > 2*plat_sdl_overlay->h);
area.w, area.h, g_screen_ppitch,
plat_sdl_overlay->w >= 2*area.w);
SDL_UnlockYUVOverlay(plat_sdl_overlay);
SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
}
@ -205,7 +229,7 @@ void plat_video_menu_end(void)
SDL_LockYUVOverlay(plat_sdl_overlay);
rgb565_to_uyvy(plat_sdl_overlay->pixels[0], shadow_fb,
g_menuscreen_pp * g_menuscreen_h, 0);
g_menuscreen_w, g_menuscreen_h, g_menuscreen_pp, 0);
SDL_UnlockYUVOverlay(plat_sdl_overlay);
SDL_DisplayYUVOverlay(plat_sdl_overlay, &dstrect);
@ -227,10 +251,10 @@ void plat_video_menu_leave(void)
void plat_video_loop_prepare(void)
{
// take over any new vout settings XXX ask plat_sdl for scaling instead!
// take over any new vout settings
plat_sdl_change_video_mode(g_menuscreen_w, g_menuscreen_h, 0);
// switch over to scaled output if available
if (plat_sdl_overlay != NULL || plat_sdl_gl_active || currentConfig.scaling != EOPT_SCALE_NONE) {
if (plat_sdl_overlay != NULL || plat_sdl_gl_active) {
g_screen_width = 320;
g_screen_height = 240;
g_screen_ppitch = g_screen_width;
@ -246,6 +270,7 @@ void plat_video_loop_prepare(void)
g_screen_ptr = plat_sdl_screen->pixels;
}
plat_video_set_buffer(g_screen_ptr);
plat_video_set_size(g_screen_width, g_screen_height);
}
void plat_early_init(void)