gpu_neon: add some intelace mode handling
authornotaz <notasas@gmail.com>
Wed, 4 Jan 2012 21:26:32 +0000 (23:26 +0200)
committernotaz <notasas@gmail.com>
Wed, 4 Jan 2012 23:41:14 +0000 (01:41 +0200)
a bit of refactoring too

frontend/main.c
frontend/menu.c
frontend/plugin_lib.h
plugins/gpu_neon/gpu.c
plugins/gpu_neon/gpu.h
plugins/gpu_neon/peops_if.c
plugins/gpu_neon/psx_gpu_if.c
plugins/gpu_neon/test.c
plugins/gpu_neon/unai_if.cpp
plugins/gpu_neon/vout_fb.c
plugins/gpu_neon/vout_sdl.c

index fd4674b..7b3aac5 100644 (file)
@@ -150,6 +150,7 @@ void emu_set_default_config(void)
        pl_rearmed_cbs.gpu_unai.abe_hack =
        pl_rearmed_cbs.gpu_unai.no_light =
        pl_rearmed_cbs.gpu_unai.no_blend = 0;
+       pl_rearmed_cbs.gpu_neon.allow_interlace = 2; // auto
 
        iUseReverb = 2;
        iUseInterpolation = 1;
index ce5c3eb..c6a52de 100644 (file)
@@ -290,6 +290,7 @@ static const struct {
        CE_INTVAL_P(gpu_unai.abe_hack),
        CE_INTVAL_P(gpu_unai.no_light),
        CE_INTVAL_P(gpu_unai.no_blend),
+       CE_INTVAL_P(gpu_neon.allow_interlace),
        CE_INTVAL_V(iUseReverb, 3),
        CE_INTVAL_V(iXAPitch, 3),
        CE_INTVAL_V(iUseInterpolation, 3),
@@ -1193,6 +1194,26 @@ static int menu_loop_gfx_options(int id, int keys)
 
 // ------------ bios/plugins ------------
 
+#ifdef __ARM_NEON__
+
+static const char h_gpu_neon[] = "Configure built-in NEON GPU plugin";
+static const char *men_gpu_interlace[] = { "Off", "On", "Auto", NULL };
+
+static menu_entry e_menu_plugin_gpu_neon[] =
+{
+       mee_enum      ("Enable interlace mode",      0, pl_rearmed_cbs.gpu_neon.allow_interlace, men_gpu_interlace),
+       mee_end,
+};
+
+static int menu_loop_plugin_gpu_neon(int id, int keys)
+{
+       int sel = 0;
+       me_loop(e_menu_plugin_gpu_neon, &sel);
+       return 0;
+}
+
+#endif
+
 static menu_entry e_menu_plugin_gpu_unai[] =
 {
        mee_onoff     ("Skip every 2nd line",        0, pl_rearmed_cbs.gpu_unai.lineskip, 1),
@@ -1210,12 +1231,12 @@ static int menu_loop_plugin_gpu_unai(int id, int keys)
 }
 
 static const char *men_gpu_dithering[] = { "None", "Game dependant", "Always", NULL };
-static const char h_gpu_0[]            = "Needed for Chrono Cross";
+//static const char h_gpu_0[]            = "Needed for Chrono Cross";
 static const char h_gpu_1[]            = "Capcom fighting games";
 static const char h_gpu_2[]            = "Black screens in Lunar";
 static const char h_gpu_3[]            = "Compatibility mode";
 static const char h_gpu_6[]            = "Pandemonium 2";
-static const char h_gpu_7[]            = "Skip every second frame";
+//static const char h_gpu_7[]            = "Skip every second frame";
 static const char h_gpu_8[]            = "Needed by Dark Forces";
 static const char h_gpu_9[]            = "better g-colors, worse textures";
 static const char h_gpu_10[]           = "Toggle busy flags after drawing";
@@ -1223,12 +1244,12 @@ static const char h_gpu_10[]           = "Toggle busy flags after drawing";
 static menu_entry e_menu_plugin_gpu_peops[] =
 {
        mee_enum      ("Dithering",                  0, pl_rearmed_cbs.gpu_peops.iUseDither, men_gpu_dithering),
-       mee_onoff_h   ("Odd/even bit hack",          0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<0, h_gpu_0),
+//     mee_onoff_h   ("Odd/even bit hack",          0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<0, h_gpu_0),
        mee_onoff_h   ("Expand screen width",        0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<1, h_gpu_1),
        mee_onoff_h   ("Ignore brightness color",    0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<2, h_gpu_2),
        mee_onoff_h   ("Disable coordinate check",   0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<3, h_gpu_3),
        mee_onoff_h   ("Lazy screen update",         0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<6, h_gpu_6),
-       mee_onoff_h   ("Old frame skipping",         0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<7, h_gpu_7),
+//     mee_onoff_h   ("Old frame skipping",         0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<7, h_gpu_7),
        mee_onoff_h   ("Repeated flat tex triangles ",0,pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<8, h_gpu_8),
        mee_onoff_h   ("Draw quads with triangles",  0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<9, h_gpu_9),
        mee_onoff_h   ("Fake 'gpu busy' states",     0, pl_rearmed_cbs.gpu_peops.dwActFixes, 1<<10, h_gpu_10),
@@ -1279,6 +1300,9 @@ static menu_entry e_menu_plugin_options[] =
        mee_enum_h    ("BIOS",                          0, bios_sel, bioses, h_bios),
        mee_enum_h    ("GPU plugin",                    0, gpu_plugsel, gpu_plugins, h_plugin_xpu),
        mee_enum_h    ("SPU plugin",                    0, spu_plugsel, spu_plugins, h_plugin_xpu),
+#ifdef __ARM_NEON__
+       mee_handler_h ("Configure built-in GPU plugin", menu_loop_plugin_gpu_neon, h_gpu_neon),
+#endif
        mee_handler_h ("Configure gpu_peops plugin",    menu_loop_plugin_gpu_peops, h_gpu_peops),
        mee_handler_h ("Configure PCSX4ALL GPU plugin", menu_loop_plugin_gpu_unai, h_gpu_unai),
        mee_handler_h ("Configure built-in SPU plugin", menu_loop_plugin_spu, h_spu),
index 2806056..44c5630 100644 (file)
@@ -61,6 +61,9 @@ struct rearmed_cbs {
                int   no_light, no_blend;
                int   lineskip;
        } gpu_unai;
+       struct {
+               int   allow_interlace; // 0 off, 1 on, 2 guess
+       } gpu_neon;
 };
 
 extern struct rearmed_cbs pl_rearmed_cbs;
index 02dd372..339cdfd 100644 (file)
@@ -29,6 +29,7 @@ struct psx_gpu gpu __attribute__((aligned(2048)));
 static noinline void do_reset(void)
 {
   memset(gpu.regs, 0, sizeof(gpu.regs));
+  memset(gpu.ex_regs, 0, sizeof(gpu.ex_regs));
   gpu.status.reg = 0x14802000;
   gpu.gp0 = 0;
   gpu.regs[3] = 1;
@@ -264,10 +265,10 @@ static void start_vram_transfer(uint32_t pos_word, uint32_t size_word, int is_re
   if (gpu.dma.h)
     log_anomaly("start_vram_transfer while old unfinished\n");
 
-  gpu.dma.x = pos_word & 1023;
-  gpu.dma.y = (pos_word >> 16) & 511;
-  gpu.dma.w = size_word & 0xffff; // ?
-  gpu.dma.h = size_word >> 16;
+  gpu.dma.x = pos_word & 0x3ff;
+  gpu.dma.y = (pos_word >> 16) & 0x1ff;
+  gpu.dma.w = size_word & 0x3ff;
+  gpu.dma.h = (size_word >> 16) & 0x1ff;
   gpu.dma.offset = 0;
 
   renderer_flush_queues();
@@ -275,6 +276,7 @@ static void start_vram_transfer(uint32_t pos_word, uint32_t size_word, int is_re
     gpu.status.img = 1;
     // XXX: wrong for width 1
     memcpy(&gpu.gp0, VRAM_MEM_XY(gpu.dma.x, gpu.dma.y), 4);
+    gpu.state.last_vram_read_frame = *gpu.state.frame_count;
   }
   else {
     renderer_invalidate_caches(gpu.dma.x, gpu.dma.y, gpu.dma.w, gpu.dma.h);
@@ -362,7 +364,7 @@ static int check_cmd(uint32_t *data, int count)
   return count - pos;
 }
 
-void flush_cmd_buffer(void)
+static void flush_cmd_buffer(void)
 {
   int left = check_cmd(gpu.cmd_buffer, gpu.cmd_len);
   if (left > 0)
@@ -533,8 +535,65 @@ long GPUfreeze(uint32_t type, struct GPUFreeze *freeze)
   return 1;
 }
 
+void GPUupdateLace(void)
+{
+  if (gpu.cmd_len > 0)
+    flush_cmd_buffer();
+  renderer_flush_queues();
+
+  if (gpu.status.blanking || !gpu.state.fb_dirty)
+    return;
+
+  if (gpu.frameskip.set) {
+    if (!gpu.frameskip.frame_ready) {
+      if (*gpu.state.frame_count - gpu.frameskip.last_flip_frame < 9)
+        return;
+      gpu.frameskip.active = 0;
+    }
+    gpu.frameskip.frame_ready = 0;
+  }
+
+  vout_update();
+  gpu.state.fb_dirty = 0;
+}
+
 void GPUvBlank(int is_vblank, int lcf)
 {
+  int interlace = gpu.state.allow_interlace
+    && gpu.status.interlace && gpu.status.dheight;
+  // interlace doesn't look nice on progressive displays,
+  // so we have this "auto" mode here for games that don't read vram
+  if (gpu.state.allow_interlace == 2
+      && *gpu.state.frame_count - gpu.state.last_vram_read_frame > 1)
+  {
+    interlace = 0;
+  }
+  if (interlace || interlace != gpu.state.old_interlace) {
+    gpu.state.old_interlace = interlace;
+
+    if (gpu.cmd_len > 0)
+      flush_cmd_buffer();
+    renderer_flush_queues();
+    renderer_set_interlace(interlace, !lcf);
+  }
+}
+
+#include "../../frontend/plugin_lib.h"
+
+void GPUrearmedCallbacks(const struct rearmed_cbs *cbs)
+{
+  gpu.frameskip.set = cbs->frameskip;
+  gpu.frameskip.advice = &cbs->fskip_advice;
+  gpu.frameskip.active = 0;
+  gpu.frameskip.frame_ready = 1;
+  gpu.state.hcnt = cbs->gpu_hcnt;
+  gpu.state.frame_count = cbs->gpu_frame_count;
+  gpu.state.allow_interlace = cbs->gpu_neon.allow_interlace;
+
+  if (cbs->pl_vout_set_raw_vram)
+    cbs->pl_vout_set_raw_vram(gpu.vram);
+  renderer_set_config(cbs);
+  vout_set_config(cbs);
 }
 
 // vim:shiftwidth=2:expandtab
index 6aa933e..36fdef8 100644 (file)
@@ -64,6 +64,8 @@ struct psx_gpu {
   uint32_t zero;
   struct {
     uint32_t fb_dirty:1;
+    uint32_t old_interlace:1;
+    uint32_t allow_interlace:2;
     uint32_t *frame_count;
     uint32_t *hcnt; /* hsync count */
     struct {
@@ -72,6 +74,7 @@ struct psx_gpu {
       uint32_t frame;
       uint32_t hcnt;
     } last_list;
+    uint32_t last_vram_read_frame;
   } state;
   struct {
     int32_t set:3; /* -1 auto, 0 off, 1-3 fixed */
@@ -87,7 +90,6 @@ struct psx_gpu {
 extern struct psx_gpu gpu;
 
 extern const unsigned char cmd_lengths[256];
-void flush_cmd_buffer(void);
 
 void do_cmd_list(uint32_t *list, int count);
 
@@ -97,10 +99,13 @@ int  renderer_init(void);
 void renderer_sync_ecmds(uint32_t * ecmds);
 void renderer_invalidate_caches(int x, int y, int w, int h);
 void renderer_flush_queues(void);
+void renderer_set_interlace(int enable, int is_odd);
 void renderer_set_config(const struct rearmed_cbs *config);
 
-int vout_init(void);
-int vout_finish(void);
+int  vout_init(void);
+int  vout_finish(void);
+void vout_update(void);
+void vout_set_config(const struct rearmed_cbs *config);
 
 /* listing these here for correct linkage if rasterizer uses c++ */
 struct GPUFreeze;
index 48fd431..2e967f2 100644 (file)
@@ -385,6 +385,10 @@ void renderer_flush_queues(void)
 {
 }
 
+void renderer_set_interlace(int enable, int is_odd)
+{
+}
+
 #include "../../frontend/plugin_lib.h"
 
 void renderer_set_config(const struct rearmed_cbs *cbs)
index 8907ac0..470f68e 100644 (file)
@@ -48,6 +48,15 @@ void renderer_flush_queues(void)
   flush_render_block_buffer(&egpu);
 }
 
+void renderer_set_interlace(int enable, int is_odd)
+{
+  egpu.interlace_mode &= ~(RENDER_INTERLACE_ENABLED|RENDER_INTERLACE_ODD);
+  if (enable)
+    egpu.interlace_mode |= RENDER_INTERLACE_ENABLED;
+  if (is_odd)
+    egpu.interlace_mode |= RENDER_INTERLACE_ODD;
+}
+
 void renderer_set_config(const struct rearmed_cbs *cbs)
 {
 }
index be271b6..e523e20 100644 (file)
@@ -89,6 +89,8 @@ int main(int argc, char *argv[])
   pcnt_init();
   renderer_init();
   memcpy(gpu.vram, state.vram, sizeof(gpu.vram));
+  if ((state.gpu_register[8] & 0x24) == 0x24)
+    renderer_set_interlace(1, !(state.status >> 31));
 
   start_cycles = pcnt_get();
 
index 4e3e7f9..072993a 100644 (file)
@@ -272,6 +272,10 @@ void renderer_flush_queues(void)
 {
 }
 
+void renderer_set_interlace(int enable, int is_odd)
+{
+}
+
 #ifndef TEST
 
 #include "../../frontend/plugin_lib.h"
index a45b5f1..20c8ff3 100644 (file)
@@ -88,28 +88,13 @@ static void blit(void)
   screen_buf = cbs->pl_vout_flip();
 }
 
-void GPUupdateLace(void)
+void vout_update(void)
 {
-  if (gpu.status.blanking || !gpu.state.fb_dirty)
-    return;
-
-  if (gpu.frameskip.set) {
-    if (!gpu.frameskip.frame_ready) {
-      if (*gpu.state.frame_count - gpu.frameskip.last_flip_frame < 9)
-        return;
-    }
-    gpu.frameskip.frame_ready = 0;
-  }
-
-  if (gpu.cmd_len > 0)
-    flush_cmd_buffer();
-  renderer_flush_queues();
   check_mode_change();
   if (cbs->pl_vout_raw_flip)
     cbs->pl_vout_raw_flip(gpu.screen.x, gpu.screen.y);
   else
     blit();
-  gpu.state.fb_dirty = 0;
 }
 
 long GPUopen(void **unused)
@@ -128,19 +113,9 @@ long GPUclose(void)
   return 0;
 }
 
-void GPUrearmedCallbacks(const struct rearmed_cbs *cbs_)
+void vout_set_config(const struct rearmed_cbs *cbs_)
 {
   cbs = cbs_;
-  gpu.frameskip.set = cbs->frameskip;
-  gpu.frameskip.advice = &cbs->fskip_advice;
-  gpu.frameskip.active = 0;
-  gpu.frameskip.frame_ready = 1;
-  gpu.state.hcnt = cbs->gpu_hcnt;
-  gpu.state.frame_count = cbs->gpu_frame_count;
-
-  if (cbs->pl_vout_set_raw_vram)
-    cbs->pl_vout_set_raw_vram(gpu.vram);
-  renderer_set_config(cbs_);
 }
 
 // vim:shiftwidth=2:expandtab
index 0830c56..db1ae96 100644 (file)
@@ -48,7 +48,7 @@ int vout_finish(void)
   return 0;
 }
 
-static void blit(void)
+void vout_update(void)
 {
   uint32_t *d;
   int i;
@@ -77,17 +77,6 @@ static void blit(void)
   SDL_UpdateRect(screen, 0, 0, 1024, 512);
 }
 
-void GPUupdateLace(void)
-{
-  if (!gpu.status.blanking && gpu.state.fb_dirty) {
-    if (gpu.cmd_len > 0)
-      flush_cmd_buffer();
-    renderer_flush_queues();
-    blit();
-    gpu.state.fb_dirty = 0;
-  }
-}
-
 long GPUopen(void **dpy)
 {
   *dpy = x11_display;
@@ -99,16 +88,8 @@ long GPUclose(void)
   return 0;
 }
 
-#include "../../frontend/plugin_lib.h"
-
-void GPUrearmedCallbacks(const struct rearmed_cbs *cbs)
+void vout_set_config(const struct rearmed_cbs *cbs)
 {
-  gpu.state.hcnt = cbs->gpu_hcnt;
-  gpu.state.frame_count = cbs->gpu_frame_count;
-
-  if (cbs->pl_vout_set_raw_vram)
-    cbs->pl_vout_set_raw_vram(gpu.vram);
-  renderer_set_config(cbs);
 }
 
 // vim:shiftwidth=2:expandtab