frontend: overlay improvements
authornotaz <notasas@gmail.com>
Sat, 17 Nov 2012 22:31:30 +0000 (00:31 +0200)
committernotaz <notasas@gmail.com>
Sat, 17 Nov 2012 23:40:00 +0000 (01:40 +0200)
work directly on psx vram

Makefile
frontend/libpicofe
frontend/main.c
frontend/plat_sdl.c
frontend/plugin_lib.c
frontend/plugin_lib.h
plugins/gpulib/cspace.c
plugins/gpulib/cspace.h

index 2e67178..a7d61d9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -99,10 +99,9 @@ endif
 
 # builtin gpu
 OBJS += plugins/gpulib/gpu.o plugins/gpulib/vout_pl.o
+OBJS += plugins/gpulib/cspace.o
 ifeq "$(HAVE_NEON)" "1"
 OBJS += plugins/gpulib/cspace_neon.o
-else
-OBJS += plugins/gpulib/cspace.o
 endif
 ifeq "$(BUILTIN_GPU)" "neon"
 OBJS += plugins/gpu_neon/psx_gpu_if.o plugins/gpu_neon/psx_gpu/psx_gpu_arm_neon.o
index 9227a77..3e1124f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 9227a7770e0d144109ee34ae34a270c6d06b9f80
+Subproject commit 3e1124f989febba80ef582c1200153ed176226f0
index 29df6d9..f5da18b 100644 (file)
@@ -263,6 +263,10 @@ do_state_slot:
                break;
        case SACTION_TOGGLE_FULLSCREEN:
                g_fullscreen = !g_fullscreen;
+               if (GPU_open != NULL && GPU_close != NULL) {
+                       GPU_close();
+                       GPU_open(&gpuDisp, "PCSX", NULL);
+               }
                break;
        case SACTION_SCREENSHOT:
                {
index a899c15..3661149 100644 (file)
@@ -14,6 +14,8 @@
 #include "libpicofe/input.h"
 #include "libpicofe/in_sdl.h"
 #include "libpicofe/menu.h"
+#include "libpicofe/fonts.h"
+#include "../plugins/gpulib/cspace.h"
 #include "plugin_lib.h"
 #include "main.h"
 #include "menu.h"
@@ -58,7 +60,9 @@ static int window_w, window_h;
 static int fs_w, fs_h;
 static int psx_w, psx_h;
 static void *menubg_img;
-static int in_menu, pending_resize, old_fullscreen;
+static int in_menu, old_fullscreen;
+
+static void overlay_clear(void);
 
 static int change_video_mode(int w, int h)
 {
@@ -98,6 +102,8 @@ static int change_video_mode(int w, int h)
       if (!overlay->hw_overlay)
         fprintf(stderr, "warning: video overlay is not hardware accelerated,"
                         " you may want to disable it.\n");
+
+      overlay_clear();
     }
     else {
       fprintf(stderr, "warning: could not create overlay.\n");
@@ -130,7 +136,7 @@ static void event_handler(void *event_)
     if (overlay != NULL && !g_fullscreen && !old_fullscreen) {
       window_w = event->resize.w;
       window_h = event->resize.h;
-      pending_resize = 1;
+      change_video_mode(psx_w, psx_h);
     }
   }
 }
@@ -189,6 +195,8 @@ void plat_init(void)
   in_sdl_init(in_sdl_defbinds, event_handler);
   in_probe();
   pl_rearmed_cbs.only_16bpp = 1;
+
+  bgr_to_uyvy_init();
   return;
 
 fail:
@@ -207,65 +215,96 @@ void plat_gvideo_open(int is_pal)
 {
 }
 
-void *plat_gvideo_set_mode(int *w, int *h, int *bpp)
+static void uyvy_to_rgb565(void *d, const void *s, int pixels)
 {
-  change_video_mode(*w, *h);
-  return screen->pixels;
+  unsigned short *dst = d;
+  const unsigned int *src = s;
+  int v;
+
+  // no colors, for now
+  for (; pixels > 0; src++, dst += 2, pixels -= 2) {
+    v = (*src >> 8) & 0xff;
+    v = (v - 16) * 255 / 219 / 8;
+    dst[0] = (v << 11) | (v << 6) | v;
+
+    v = (*src >> 24) & 0xff;
+    v = (v - 16) * 255 / 219 / 8;
+    dst[1] = (v << 11) | (v << 6) | v;
+  }
 }
 
-static void test_convert(void *d, const void *s, int pixels)
+static void overlay_clear(void)
 {
-  unsigned int *dst = d;
-  const unsigned short *src = s;
-  int r0, g0, b0, r1, g1, b1;
-  int y0, y1, u, v;
-
-  for (; pixels > 0; src += 2, dst++, pixels -= 2) {
-    r0 =  src[0] >> 11;
-    g0 = (src[0] >> 6) & 0x1f;
-    b0 =  src[0] & 0x1f;
-    r1 =  src[1] >> 11;
-    g1 = (src[1] >> 6) & 0x1f;
-    b1 =  src[1] & 0x1f;
-    y0 = (int)((0.299f * r0) + (0.587f * g0) + (0.114f * b0));
-    y1 = (int)((0.299f * r1) + (0.587f * g1) + (0.114f * b1));
-    //u = (int)(((-0.169f * r0) + (-0.331f * g0) + ( 0.499f * b0)) * 8) + 128;
-    //v = (int)((( 0.499f * r0) + (-0.418f * g0) + (-0.0813f * b0)) * 8) + 128;
-    u = (int)(8 * 0.565f * (b0 - y0)) + 128;
-    v = (int)(8 * 0.713f * (r0 - y0)) + 128;
-    // valid Y range seems to be 16..235
-    y0 = 16 + 219 * y0 / 31;
-    y1 = 16 + 219 * y1 / 31;
-
-    if (y0 < 0 || y0 > 255 || y1 < 0 || y1 > 255
-        || u < 0 || u > 255 || v < 0 || v > 255)
-    {
-      printf("oor: %d, %d, %d, %d\n", y0, y1, u, v);
-    }
-    *dst = (y1 << 24) | (v << 16) | (y0 << 8) | u;
+  int pixels = overlay->w * overlay->h;
+  int *dst = (int *)overlay->pixels[0];
+  int v = 0x10801080;
+
+  for (; pixels > 0; dst += 4, pixels -= 2 * 4)
+    dst[0] = dst[1] = dst[2] = dst[3] = v;
+
+  for (; pixels > 0; dst++, pixels -= 2)
+    *dst = v;
+}
+
+static void overlay_blit(int doffs, const void *src_, int w, int h,
+                         int sstride, int bgr24)
+{
+  const unsigned short *src = src_;
+  unsigned short *dst;
+  int dstride = overlay->w;
+
+  SDL_LockYUVOverlay(overlay);
+  dst = (void *)overlay->pixels[0];
+
+  dst += doffs;
+  if (bgr24) {
+    for (; h > 0; dst += dstride, src += sstride, h--)
+      bgr888_to_uyvy(dst, src, w);
+  }
+  else {
+    for (; h > 0; dst += dstride, src += sstride, h--)
+      bgr555_to_uyvy(dst, src, w);
+  }
+
+  SDL_UnlockYUVOverlay(overlay);
+}
+
+static void overlay_hud_print(int x, int y, const char *str, int bpp)
+{
+  SDL_LockYUVOverlay(overlay);
+  basic_text_out_uyvy_nf(overlay->pixels[0], overlay->w, x, y, str);
+  SDL_UnlockYUVOverlay(overlay);
+}
+
+void *plat_gvideo_set_mode(int *w, int *h, int *bpp)
+{
+  change_video_mode(*w, *h);
+  if (overlay != NULL) {
+    pl_plat_clear = overlay_clear;
+    pl_plat_blit = overlay_blit;
+    pl_plat_hud_print = overlay_hud_print;
+    return NULL;
+  }
+  else {
+    pl_plat_clear = NULL;
+    pl_plat_blit = NULL;
+    pl_plat_hud_print = NULL;
+    return screen->pixels;
   }
 }
 
-/* XXX: missing SDL_LockSurface() */
 void *plat_gvideo_flip(void)
 {
   if (!in_menu && overlay != NULL) {
     SDL_Rect dstrect = { 0, 0, screen->w, screen->h };
-    SDL_LockYUVOverlay(overlay);
-    test_convert(overlay->pixels[0], screen->pixels, overlay->w * overlay->h);
-    SDL_UnlockYUVOverlay(overlay);
     SDL_DisplayYUVOverlay(overlay, &dstrect);
+    return NULL;
   }
-  else
+  else {
+    // XXX: missing SDL_LockSurface()
     SDL_Flip(screen);
-
-  if (pending_resize || g_fullscreen != old_fullscreen) {
-    // must be done here so that correct buffer is returned
-    change_video_mode(psx_w, psx_h);
-    pending_resize = 0;
+    return screen->pixels;
   }
-
-  return screen->pixels;
 }
 
 void plat_gvideo_close(void)
@@ -277,8 +316,10 @@ void plat_video_menu_enter(int is_rom_loaded)
   in_menu = 1;
 
   /* surface will be lost, must adjust pl_vout_buf for menu bg */
-  // FIXME?
-  memcpy(menubg_img, screen->pixels, psx_w * psx_h * 2);
+  if (overlay != NULL)
+    uyvy_to_rgb565(menubg_img, overlay->pixels[0], psx_w * psx_h);
+  else
+    memcpy(menubg_img, screen->pixels, psx_w * psx_h * 2);
   pl_vout_buf = menubg_img;
 
   change_video_mode(g_menuscreen_w, g_menuscreen_h);
index 9cbfe59..a0f16e9 100644 (file)
@@ -49,6 +49,12 @@ static int vsync_cnt;
 static int is_pal, frame_interval, frame_interval1024;
 static int vsync_usec_time;
 
+// platform hooks
+void (*pl_plat_clear)(void);
+void (*pl_plat_blit)(int doffs, const void *src, int w, int h,
+                    int sstride, int bgr24);
+void (*pl_plat_hud_print)(int x, int y, const char *str, int bpp);
+
 
 static __attribute__((noinline)) int get_cpu_ticks(void)
 {
@@ -66,31 +72,48 @@ static __attribute__((noinline)) int get_cpu_ticks(void)
 
        sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu", &utime);
        ret = utime - last_utime;
+       if (ret > 200)
+               ret = 0;
        last_utime = utime;
        return ret;
 }
 
+static void hud_print(void *fb, int w, int x, int y, const char *text)
+{
+       if (pl_plat_hud_print)
+               pl_plat_hud_print(x, y, text, pl_vout_bpp);
+       else if (pl_vout_bpp == 16)
+               basic_text_out16_nf(fb, w, x, y, text);
+}
+
+static void hud_printf(void *fb, int w, int x, int y, const char *texto, ...)
+{
+       va_list args;
+       char    buffer[256];
+
+       va_start(args, texto);
+       vsnprintf(buffer, sizeof(buffer), texto, args);
+       va_end(args);
+
+       hud_print(fb, w, x, y, buffer);
+}
+
 static void print_msg(int h, int border)
 {
-       if (pl_vout_bpp == 16)
-               basic_text_out16_nf(pl_vout_buf, pl_vout_w,
-                       border + 2, h - 10, hud_msg);
+       hud_print(pl_vout_buf, pl_vout_w, border + 2, h - 10, hud_msg);
 }
 
 static void print_fps(int h, int border)
 {
-       if (pl_vout_bpp == 16)
-               basic_text_out16(pl_vout_buf, pl_vout_w,
-                       border + 2, h - 10, "%2d %4.1f",
-                       pl_rearmed_cbs.flips_per_sec, pl_rearmed_cbs.vsps_cur);
+       hud_printf(pl_vout_buf, pl_vout_w, border + 2, h - 10,
+               "%2d %4.1f", pl_rearmed_cbs.flips_per_sec,
+               pl_rearmed_cbs.vsps_cur);
 }
 
 static void print_cpu_usage(int w, int h, int border)
 {
-       if (pl_vout_bpp == 16)
-               basic_text_out16(pl_vout_buf, pl_vout_w,
-                       pl_vout_w - border - 28, h - 10,
-                       "%3d", pl_rearmed_cbs.cpu_usage);
+       hud_printf(pl_vout_buf, pl_vout_w, pl_vout_w - border - 28, h - 10,
+               "%3d", pl_rearmed_cbs.cpu_usage);
 }
 
 // draw 192x8 status of 24 sound channels
@@ -106,7 +129,7 @@ static __attribute__((noinline)) void draw_active_chans(int vout_w, int vout_h)
        unsigned short *d, p;
        int c, x, y;
 
-       if (pl_vout_bpp != 16)
+       if (dest == NULL || pl_vout_bpp != 16)
                return;
 
        spu_get_debug_info(&live_chans, &run_chans, &fmod_chans, &noise_chans);
@@ -238,7 +261,7 @@ static void pl_vout_set_mode(int w, int h, int raw_w, int raw_h, int bpp)
        update_layer_size(vout_w, vout_h);
 
        pl_vout_buf = plat_gvideo_set_mode(&vout_w, &vout_h, &vout_bpp);
-       if (pl_vout_buf == NULL)
+       if (pl_vout_buf == NULL && pl_plat_blit == NULL)
                fprintf(stderr, "failed to set mode %dx%d@%d\n",
                        vout_w, vout_h, psx_bpp);
        else {
@@ -260,28 +283,43 @@ static void pl_vout_flip(const void *vram, int stride, int bgr24, int w, int h)
 
        pcnt_start(PCNT_BLIT);
 
-       if (dest == NULL)
-               goto out;
-
        if (vram == NULL) {
                // blanking
-               memset(pl_vout_buf, 0, dstride * pl_vout_h * pl_vout_bpp / 8);
-               goto out;
+               if (pl_plat_clear)
+                       pl_plat_clear();
+               else
+                       memset(pl_vout_buf, 0,
+                               dstride * pl_vout_h * pl_vout_bpp / 8);
+               goto out_hud;
        }
 
        // borders
        doffs = (dstride - w * pl_vout_scale) / 2 & ~1;
-       dest += doffs * 2;
 
        if (doffs > doffs_old)
                clear_counter = 2;
        doffs_old = doffs;
 
        if (clear_counter > 0) {
-               memset(pl_vout_buf, 0, dstride * pl_vout_h * pl_vout_bpp / 8);
+               if (pl_plat_clear)
+                       pl_plat_clear();
+               else
+                       memset(pl_vout_buf, 0,
+                               dstride * pl_vout_h * pl_vout_bpp / 8);
                clear_counter--;
        }
 
+       if (pl_plat_blit)
+       {
+               pl_plat_blit(doffs, src, w, h, stride, bgr24);
+               goto out_hud;
+       }
+
+       if (dest == NULL)
+               goto out;
+
+       dest += doffs * 2;
+
        if (bgr24)
        {
                if (pl_rearmed_cbs.only_16bpp) {
@@ -304,12 +342,12 @@ static void pl_vout_flip(const void *vram, int stride, int bgr24, int w, int h)
        else if (soft_filter == SOFT_FILTER_SCALE2X && pl_vout_scale == 2)
        {
                neon_scale2x_16_16(src, (void *)dest, w,
-                       stride * 2, dstride * 2, h1);
+                       stride * 2, dstride * 2, h);
        }
        else if (soft_filter == SOFT_FILTER_EAGLE2X && pl_vout_scale == 2)
        {
                neon_eagle2x_16_16(src, (void *)dest, w,
-                       stride * 2, dstride * 2, h1);
+                       stride * 2, dstride * 2, h);
        }
 #endif
        else
@@ -320,6 +358,7 @@ static void pl_vout_flip(const void *vram, int stride, int bgr24, int w, int h)
                }
        }
 
+out_hud:
        pl_print_hud(w * pl_vout_scale, h * pl_vout_scale, 0);
 
 out:
index 2f6c680..bec16b2 100644 (file)
@@ -93,6 +93,12 @@ enum gpu_plugin_caps {
        GPU_CAP_SUPPORTS_2X = (1 << 1),
 };
 
+// platform hooks
+extern void (*pl_plat_clear)(void);
+extern void (*pl_plat_blit)(int doffs, const void *src,
+                           int w, int h, int sstride, int bgr24);
+extern void (*pl_plat_hud_print)(int x, int y, const char *str, int bpp);
+
 #ifndef ARRAY_SIZE
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
 #endif
index 1d5718c..8e3bee9 100644 (file)
@@ -1,3 +1,13 @@
+/*
+ * (C) GraÅžvydas "notaz" Ignotas, 2011,2012
+ *
+ * This work is licensed under the terms of any of these licenses
+ * (at your option):
+ *  - GNU GPL, version 2 or later.
+ *  - GNU LGPL, version 2.1 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
 #include "cspace.h"
 
 /*
@@ -5,6 +15,8 @@
  * in favor of NEON version or platform-specific conversion
  */
 
+#ifndef __ARM_NEON__
+
 void bgr555_to_rgb565(void *dst_, const void *src_, int bytes)
 {
        const unsigned int *src = src_;
@@ -42,3 +54,92 @@ void bgr888_to_rgb565(void *dst_, const void *src_, int bytes)
 void rgb888_to_rgb565(void *dst, const void *src, int bytes) {}
 void bgr888_to_rgb888(void *dst, const void *src, int bytes) {}
 
+#endif // __ARM_NEON__
+
+/* YUV stuff */
+static int yuv_ry[32], yuv_gy[32], yuv_by[32];
+static unsigned char yuv_u[32 * 2], yuv_v[32 * 2];
+
+void bgr_to_uyvy_init(void)
+{
+  int i, v;
+
+  /* init yuv converter:
+    y0 = (int)((0.299f * r0) + (0.587f * g0) + (0.114f * b0));
+    y1 = (int)((0.299f * r1) + (0.587f * g1) + (0.114f * b1));
+    u = (int)(8 * 0.565f * (b0 - y0)) + 128;
+    v = (int)(8 * 0.713f * (r0 - y0)) + 128;
+  */
+  for (i = 0; i < 32; i++) {
+    yuv_ry[i] = (int)(0.299f * i * 65536.0f + 0.5f);
+    yuv_gy[i] = (int)(0.587f * i * 65536.0f + 0.5f);
+    yuv_by[i] = (int)(0.114f * i * 65536.0f + 0.5f);
+  }
+  for (i = -32; i < 32; i++) {
+    v = (int)(8 * 0.565f * i) + 128;
+    if (v < 0)
+      v = 0;
+    if (v > 255)
+      v = 255;
+    yuv_u[i + 32] = v;
+    v = (int)(8 * 0.713f * i) + 128;
+    if (v < 0)
+      v = 0;
+    if (v > 255)
+      v = 255;
+    yuv_v[i + 32] = v;
+  }
+}
+
+void bgr555_to_uyvy(void *d, const void *s, int pixels)
+{
+  unsigned int *dst = d;
+  const unsigned short *src = s;
+  const unsigned char *yu = yuv_u + 32;
+  const unsigned char *yv = yuv_v + 32;
+  int r0, g0, b0, r1, g1, b1;
+  int y0, y1, u, v;
+
+  for (; pixels > 0; src += 2, dst++, pixels -= 2)
+  {
+    b0 = (src[0] >> 10) & 0x1f;
+    g0 = (src[0] >> 5) & 0x1f;
+    r0 =  src[0] & 0x1f;
+    b1 = (src[1] >> 10) & 0x1f;
+    g1 = (src[1] >> 5) & 0x1f;
+    r1 =  src[1] & 0x1f;
+    y0 = (yuv_ry[r0] + yuv_gy[g0] + yuv_by[b0]) >> 16;
+    y1 = (yuv_ry[r1] + yuv_gy[g1] + yuv_by[b1]) >> 16;
+    u = yu[b0 - y0];
+    v = yv[r0 - y0];
+    // valid Y range seems to be 16..235
+    y0 = 16 + 219 * y0 / 31;
+    y1 = 16 + 219 * y1 / 31;
+
+    *dst = (y1 << 24) | (v << 16) | (y0 << 8) | u;
+  }
+}
+
+void bgr888_to_uyvy(void *d, const void *s, int pixels)
+{
+  unsigned int *dst = d;
+  const unsigned char *src8 = s;
+  const unsigned char *yu = yuv_u + 32;
+  const unsigned char *yv = yuv_v + 32;
+  int r0, g0, b0, r1, g1, b1;
+  int y0, y1, u, v;
+
+  for (; pixels > 0; src8 += 3*2, dst++, pixels -= 2)
+  {
+    r0 = src8[0], g0 = src8[1], b0 = src8[2];
+    r1 = src8[3], g1 = src8[4], b1 = src8[5];
+    y0 = (r0 * 19595 + g0 * 38470 + b0 * 7471) >> 16;
+    y1 = (r1 * 19595 + g1 * 38470 + b1 * 7471) >> 16;
+    u = yu[(b0 - y0) / 8];
+    v = yv[(r0 - y0) / 8];
+    y0 = 16 + 219 * y0 / 255;
+    y1 = 16 + 219 * y1 / 255;
+
+    *dst = (y1 << 24) | (v << 16) | (y0 << 8) | u;
+  }
+}
index 8c9bcfa..95eae85 100644 (file)
@@ -8,6 +8,10 @@ void bgr888_to_rgb888(void *dst, const void *src, int bytes);
 void bgr888_to_rgb565(void *dst, const void *src, int bytes);
 void rgb888_to_rgb565(void *dst, const void *src, int bytes);
 
+void bgr_to_uyvy_init(void);
+void bgr555_to_uyvy(void *d, const void *s, int pixels);
+void bgr888_to_uyvy(void *d, const void *s, int pixels);
+
 #ifdef __cplusplus
 }
 #endif