aboutsummaryrefslogtreecommitdiff
path: root/frontend
diff options
context:
space:
mode:
authornotaz2012-11-02 03:07:05 +0200
committernotaz2012-11-02 03:07:05 +0200
commit2857d72e4ca743bba3cf55e298949e24d97dff02 (patch)
tree3742f3cd7cb1c10fc42fc4b581fff9c4ead3d9ce /frontend
parent0e53ec55691229fee1cbb7c23b305be6a59431c4 (diff)
parentbcb62992749a7f66e9a16a8022e090ff334c4424 (diff)
downloadpcsx_rearmed-2857d72e4ca743bba3cf55e298949e24d97dff02.tar.gz
pcsx_rearmed-2857d72e4ca743bba3cf55e298949e24d97dff02.tar.bz2
pcsx_rearmed-2857d72e4ca743bba3cf55e298949e24d97dff02.zip
Merge branch 'enhancement'
Conflicts: frontend/libretro.c
Diffstat (limited to 'frontend')
-rw-r--r--frontend/common/plat.h4
m---------frontend/libpicofe0
-rw-r--r--frontend/libretro.c45
-rw-r--r--frontend/linux/plat.c49
-rw-r--r--frontend/main.c10
-rw-r--r--frontend/main.h1
-rw-r--r--frontend/menu.c30
-rw-r--r--frontend/menu.h8
-rwxr-xr-xfrontend/pandora/pcsx.sh5
-rw-r--r--frontend/plat_omap.c5
-rw-r--r--frontend/plat_pandora.c1
-rw-r--r--frontend/plat_pollux.c33
-rw-r--r--frontend/plugin_lib.c251
-rw-r--r--frontend/plugin_lib.h23
14 files changed, 390 insertions, 75 deletions
diff --git a/frontend/common/plat.h b/frontend/common/plat.h
index 0a9fc0b..1fb8767 100644
--- a/frontend/common/plat.h
+++ b/frontend/common/plat.h
@@ -45,6 +45,10 @@ int plat_is_dir(const char *path);
int plat_wait_event(int *fds_hnds, int count, int timeout_ms);
void plat_sleep_ms(int ms);
+void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed);
+void *plat_mremap(void *ptr, size_t oldsize, size_t newsize);
+void plat_munmap(void *ptr, size_t size);
+
/* timers, to be used for time diff and must refer to the same clock */
unsigned int plat_get_ticks_ms(void);
unsigned int plat_get_ticks_us(void);
diff --git a/frontend/libpicofe b/frontend/libpicofe
new file mode 160000
+Subproject 6ce097ba2f3cd1c269bacd032b775b6d296433f
diff --git a/frontend/libretro.c b/frontend/libretro.c
index 4305aa7..1eb2147 100644
--- a/frontend/libretro.c
+++ b/frontend/libretro.c
@@ -13,6 +13,7 @@
#include "../libpcsxcore/psxcounters.h"
#include "../libpcsxcore/new_dynarec/new_dynarec.h"
#include "../plugins/dfsound/out.h"
+#include "../plugins/gpulib/cspace.h"
#include "main.h"
#include "plugin.h"
#include "plugin_lib.h"
@@ -26,7 +27,6 @@ static retro_environment_t environ_cb;
static retro_audio_sample_batch_t audio_batch_cb;
static void *vout_buf;
-static int vout_width, vout_height;
static int samples_sent, samples_to_send;
static int plugins_opened;
static int native_rgb565;
@@ -42,14 +42,10 @@ static int vout_open(void)
return 0;
}
-static void *vout_set_mode(int w, int h, int bpp)
+static void vout_set_mode(int w, int h, int bpp)
{
- vout_width = w;
- vout_height = h;
- return vout_buf;
}
-/* FIXME: either teach PCSX to blit to RGB1555 or RetroArch to support RGB565 */
static void convert(void *buf, size_t bytes)
{
unsigned int i, v, *p = buf;
@@ -60,14 +56,39 @@ static void convert(void *buf, size_t bytes)
}
}
-static void *vout_flip(void)
+static void vout_flip(const void *vram, int stride, int bgr24, int w, int h)
{
- pl_rearmed_cbs.flip_cnt++;
- if (!native_rgb565)
- convert(vout_buf, vout_width * vout_height * 2);
- video_cb(vout_buf, vout_width, vout_height, vout_width * 2);
+ unsigned short *dest = vout_buf;
+ const unsigned short *src = vram;
+ int dstride = w, h1 = h;
+
+ if (vram == NULL) {
+ // blanking
+ memset(pl_vout_buf, 0, dstride * h * 2);
+ goto out;
+ }
- return vout_buf;
+ if (bgr24)
+ {
+ // XXX: could we switch to RETRO_PIXEL_FORMAT_XRGB8888 here?
+ for (; h1-- > 0; dest += dstride, src += stride)
+ {
+ bgr888_to_rgb565(dest, src, w * 3);
+ }
+ }
+ else
+ {
+ for (; h1-- > 0; dest += dstride, src += stride)
+ {
+ bgr555_to_rgb565(dest, src, w * 2);
+ }
+ }
+
+out:
+ if (!native_rgb565)
+ convert(vout_buf, w * h * 2);
+ video_cb(vout_buf, w, h, w * 2);
+ pl_rearmed_cbs.flip_cnt++;
}
static void vout_close(void)
diff --git a/frontend/linux/plat.c b/frontend/linux/plat.c
index b7152b5..4ed1e65 100644
--- a/frontend/linux/plat.c
+++ b/frontend/linux/plat.c
@@ -17,9 +17,17 @@
#include <time.h>
#include <unistd.h>
#include <sys/mman.h>
+#include <errno.h>
#include "../common/plat.h"
+/* XXX: maybe unhardcode pagesize? */
+#define HUGETLB_PAGESIZE (2 * 1024 * 1024)
+#define HUGETLB_THRESHOLD (HUGETLB_PAGESIZE / 2)
+#ifndef MAP_HUGETLB
+#define MAP_HUGETLB 0x40000 /* arch specific */
+#endif
+
int plat_is_dir(const char *path)
{
@@ -126,16 +134,36 @@ int plat_wait_event(int *fds_hnds, int count, int timeout_ms)
return ret;
}
-void *plat_mmap(unsigned long addr, size_t size)
+void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed)
{
+ static int hugetlb_disabled;
+ int prot = PROT_READ | PROT_WRITE;
+ int flags = MAP_PRIVATE | MAP_ANONYMOUS;
void *req, *ret;
req = (void *)addr;
- ret = mmap(req, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ if (need_exec)
+ prot |= PROT_EXEC;
+ if (is_fixed)
+ flags |= MAP_FIXED;
+ if (size >= HUGETLB_THRESHOLD && !hugetlb_disabled)
+ flags |= MAP_HUGETLB;
+
+ ret = mmap(req, size, prot, flags, -1, 0);
+ if (ret == MAP_FAILED && (flags & MAP_HUGETLB)) {
+ fprintf(stderr,
+ "warning: failed to do hugetlb mmap (%p, %zu): %d\n",
+ req, size, errno);
+ hugetlb_disabled = 1;
+ flags &= ~MAP_HUGETLB;
+ ret = mmap(req, size, prot, flags, -1, 0);
+ }
if (ret == MAP_FAILED)
return NULL;
- if (ret != req)
- printf("warning: mmaped to %p, requested %p\n", ret, req);
+
+ if (req != NULL && ret != req)
+ fprintf(stderr,
+ "warning: mmaped to %p, requested %p\n", ret, req);
return ret;
}
@@ -155,7 +183,18 @@ void *plat_mremap(void *ptr, size_t oldsize, size_t newsize)
void plat_munmap(void *ptr, size_t size)
{
- munmap(ptr, size);
+ int ret;
+
+ ret = munmap(ptr, size);
+ if (ret != 0 && (size & (HUGETLB_PAGESIZE - 1))) {
+ // prehaps an autorounded hugetlb mapping?
+ size = (size + HUGETLB_PAGESIZE - 1) & ~(HUGETLB_PAGESIZE - 1);
+ ret = munmap(ptr, size);
+ }
+ if (ret != 0) {
+ fprintf(stderr,
+ "munmap(%p, %zu) failed: %d\n", ptr, size, errno);
+ }
}
/* lprintf */
diff --git a/frontend/main.c b/frontend/main.c
index 19e8319..56b5cb7 100644
--- a/frontend/main.c
+++ b/frontend/main.c
@@ -143,6 +143,8 @@ void emu_set_default_config(void)
Config.PsxAuto = 1;
pl_rearmed_cbs.gpu_neon.allow_interlace = 2; // auto
+ pl_rearmed_cbs.gpu_neon.enhancement_enable =
+ pl_rearmed_cbs.gpu_neon.enhancement_no_main = 0;
pl_rearmed_cbs.gpu_peops.iUseDither = 0;
pl_rearmed_cbs.gpu_peops.dwActFixes = 1<<7;
pl_rearmed_cbs.gpu_unai.abe_hack =
@@ -230,6 +232,14 @@ do_state_slot:
pl_rearmed_cbs.frameskip == 0 ? "OFF" : "1" );
plugin_call_rearmed_cbs();
break;
+ case SACTION_SWITCH_DISPMODE:
+ pl_switch_dispmode();
+ plugin_call_rearmed_cbs();
+ if (GPU_open != NULL && GPU_close != NULL) {
+ GPU_close();
+ GPU_open(&gpuDisp, "PCSX", NULL);
+ }
+ break;
case SACTION_SCREENSHOT:
{
char buf[MAXPATHLEN];
diff --git a/frontend/main.h b/frontend/main.h
index bdb4870..a03db8b 100644
--- a/frontend/main.h
+++ b/frontend/main.h
@@ -65,6 +65,7 @@ enum sched_action {
SACTION_NEXT_SSLOT,
SACTION_PREV_SSLOT,
SACTION_TOGGLE_FSKIP,
+ SACTION_SWITCH_DISPMODE,
SACTION_SCREENSHOT,
SACTION_VOLUME_UP,
SACTION_VOLUME_DOWN,
diff --git a/frontend/menu.c b/frontend/menu.c
index 42a53e1..d3ce06c 100644
--- a/frontend/menu.c
+++ b/frontend/menu.c
@@ -75,6 +75,7 @@ typedef enum
MA_OPT_SCALER,
MA_OPT_SCALER2,
MA_OPT_FILTERING,
+ MA_OPT_FILTERING2,
MA_OPT_SCALER_C,
} menu_id;
@@ -87,7 +88,7 @@ static int psx_clock;
static int memcard1_sel, memcard2_sel;
int g_opts, g_scaler;
int soft_scaling, analog_deadzone; // for Caanoo
-int filter;
+int filter, soft_filter;
#ifdef __ARM_ARCH_7A__
#define DEFAULT_PSX_CLOCK 57
@@ -213,6 +214,7 @@ static void menu_set_defconfig(void)
frameskip = 0;
analog_deadzone = 50;
soft_scaling = 1;
+ soft_filter = 0;
psx_clock = DEFAULT_PSX_CLOCK;
region = 0;
@@ -274,6 +276,7 @@ static const struct {
CE_INTVAL(g_layer_w),
CE_INTVAL(g_layer_h),
CE_INTVAL(filter),
+ CE_INTVAL(soft_filter),
CE_INTVAL(state_slot),
CE_INTVAL(cpu_clock),
CE_INTVAL(g_opts),
@@ -288,6 +291,8 @@ static const struct {
CE_INTVAL_P(gpu_unai.no_light),
CE_INTVAL_P(gpu_unai.no_blend),
CE_INTVAL_P(gpu_neon.allow_interlace),
+ CE_INTVAL_P(gpu_neon.enhancement_enable),
+ CE_INTVAL_P(gpu_neon.enhancement_no_main),
CE_INTVAL_P(gpu_peopsgl.bDrawDither),
CE_INTVAL_P(gpu_peopsgl.iFilterType),
CE_INTVAL_P(gpu_peopsgl.iFrameTexType),
@@ -661,6 +666,7 @@ me_bind_action emuctrl_actions[] =
{ "Next Save Slot ", 1 << SACTION_NEXT_SSLOT },
{ "Toggle Frameskip ", 1 << SACTION_TOGGLE_FSKIP },
{ "Take Screenshot ", 1 << SACTION_SCREENSHOT },
+ { "Switch Renderer ", 1 << SACTION_SWITCH_DISPMODE },
{ "Enter Menu ", 1 << SACTION_ENTER_MENU },
#ifdef __ARM_ARCH_7A__ /* XXX */
{ "Minimize ", 1 << SACTION_MINIMIZE },
@@ -1029,9 +1035,15 @@ static int menu_loop_keyconfig(int id, int keys)
// ------------ gfx options menu ------------
static const char *men_scaler[] = { "1x1", "scaled 4:3", "integer scaled 4:3", "fullscreen", "custom", NULL };
+static const char *men_soft_filter[] = { "None",
+#ifdef __ARM_NEON__
+ "scale2x", "eagle2x",
+#endif
+ NULL };
+static const char *men_dummy[] = { NULL };
static const char h_cscaler[] = "Displays the scaler layer, you can resize it\n"
"using d-pad or move it using R+d-pad";
-static const char *men_dummy[] = { NULL };
+static const char h_soft_filter[] = "Works only if game uses low resolution modes";
static int menu_loop_cscaler(int id, int keys)
{
@@ -1090,6 +1102,7 @@ static menu_entry e_menu_gfx_options[] =
mee_enum ("Scaler", MA_OPT_SCALER, g_scaler, men_scaler),
mee_onoff ("Software Scaling", MA_OPT_SCALER2, soft_scaling, 1),
mee_enum ("Filter", MA_OPT_FILTERING, filter, men_dummy),
+ mee_enum_h ("Software Filter", MA_OPT_FILTERING2, soft_filter, men_soft_filter, h_soft_filter),
// mee_onoff ("Vsync", 0, vsync, 1),
mee_cust_h ("Setup custom scaler", MA_OPT_SCALER_C, menu_loop_cscaler, NULL, h_cscaler),
mee_end,
@@ -1118,18 +1131,26 @@ void menu_set_filter_list(void *filters)
#ifdef __ARM_NEON__
-static const char h_gpu_neon[] = "Configure built-in NEON GPU plugin";
+static const char h_gpu_neon[] =
+ "Configure built-in NEON GPU plugin";
+static const char h_gpu_neon_enhanced[] =
+ "Renders in double resolution at the cost of lower performance\n"
+ "(not available for high resolution games)";
+static const char h_gpu_neon_enhanced_hack[] =
+ "Speed hack for above option (glitches some games)";
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_onoff_h ("Enhanced resolution (slow)", 0, pl_rearmed_cbs.gpu_neon.enhancement_enable, 1, h_gpu_neon_enhanced),
+ mee_onoff_h ("Enhanced res. speed hack", 0, pl_rearmed_cbs.gpu_neon.enhancement_no_main, 1, h_gpu_neon_enhanced_hack),
mee_end,
};
static int menu_loop_plugin_gpu_neon(int id, int keys)
{
- int sel = 0;
+ static int sel = 0;
me_loop(e_menu_plugin_gpu_neon, &sel);
return 0;
}
@@ -2247,6 +2268,7 @@ void menu_init(void)
#ifndef __ARM_ARCH_7A__ /* XXX */
me_enable(e_menu_gfx_options, MA_OPT_SCALER, 0);
me_enable(e_menu_gfx_options, MA_OPT_FILTERING, 0);
+ me_enable(e_menu_gfx_options, MA_OPT_FILTERING2, 0);
me_enable(e_menu_gfx_options, MA_OPT_SCALER_C, 0);
me_enable(e_menu_keyconfig, MA_CTRL_NUBS_BTNS, 0);
#else
diff --git a/frontend/menu.h b/frontend/menu.h
index 2062acd..221be15 100644
--- a/frontend/menu.h
+++ b/frontend/menu.h
@@ -22,9 +22,15 @@ enum g_scaler_opts {
SCALE_CUSTOM,
};
+enum g_soft_filter_opts {
+ SOFT_FILTER_NONE,
+ SOFT_FILTER_SCALE2X,
+ SOFT_FILTER_EAGLE2X,
+};
+
extern int g_opts, g_scaler;
extern int soft_scaling, analog_deadzone;
-extern int filter;
+extern int filter, soft_filter;
extern int g_menuscreen_w;
extern int g_menuscreen_h;
diff --git a/frontend/pandora/pcsx.sh b/frontend/pandora/pcsx.sh
index 0957b94..bc1d6c5 100755
--- a/frontend/pandora/pcsx.sh
+++ b/frontend/pandora/pcsx.sh
@@ -5,10 +5,15 @@ nub0mode=`cat /proc/pandora/nub0/mode`
nub1mode=`cat /proc/pandora/nub1/mode`
/usr/pandora/scripts/op_nubchange.sh absolute absolute
+# 4MB for RAM (2+align) + 2MB for vram (1+overdraw) + 10MB for gpu_neon (8+overdraw)
+# no big deal if this fails, only performance loss
+sudo -n /usr/pandora/scripts/op_hugetlb.sh 16
+
./pcsx "$@"
# restore stuff if pcsx crashes
./picorestore
sudo -n /usr/pandora/scripts/op_lcdrate.sh 60
+sudo -n /usr/pandora/scripts/op_hugetlb.sh 0
/usr/pandora/scripts/op_nubchange.sh $nub0mode $nub1mode
diff --git a/frontend/plat_omap.c b/frontend/plat_omap.c
index b01c634..e5b6c04 100644
--- a/frontend/plat_omap.c
+++ b/frontend/plat_omap.c
@@ -52,8 +52,9 @@ static int omap_setup_layer_(int fd, int enabled, int x, int y, int w, int h)
perror("SETUP_PLANE");
}
- if (mi.size < 640*512*3*3) {
- mi.size = 640*512*3*3;
+ // upto 1024x512 (2x resolution enhancement)
+ if (mi.size < 1024*512*2 * 3) {
+ mi.size = 1024*512*2 * 3;
ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi);
if (ret != 0) {
perror("SETUP_MEM");
diff --git a/frontend/plat_pandora.c b/frontend/plat_pandora.c
index 9ec747d..b82450c 100644
--- a/frontend/plat_pandora.c
+++ b/frontend/plat_pandora.c
@@ -65,6 +65,7 @@ static const struct in_default_bind in_evdev_defbinds[] = {
{ KEY_4, IN_BINDTYPE_EMU, SACTION_NEXT_SSLOT },
{ KEY_5, IN_BINDTYPE_EMU, SACTION_TOGGLE_FSKIP },
{ KEY_6, IN_BINDTYPE_EMU, SACTION_SCREENSHOT },
+ { KEY_7, IN_BINDTYPE_EMU, SACTION_SWITCH_DISPMODE },
{ 0, 0, 0 }
};
diff --git a/frontend/plat_pollux.c b/frontend/plat_pollux.c
index 1dafb7c..52a09b1 100644
--- a/frontend/plat_pollux.c
+++ b/frontend/plat_pollux.c
@@ -305,12 +305,13 @@ static void spend_cycles(int loops)
#define DMA_REG(x) memregl[(DMA_BASE6 + x) >> 2]
/* this takes ~1.5ms, while ldm/stm ~1.95ms */
-static void raw_flip_dma(int x, int y)
+static void raw_flip_dma(const void *vram, int stride, int bgr24, int w, int h)
{
+ unsigned int pixel_offset = psx_vram - (unsigned short *)vram;
unsigned int dst = fb_paddrs[fb_work_buf] +
(fb_offset_y * 320 + fb_offset_x) * psx_bpp / 8;
- int spsx_line = y + psx_offset_y;
- int spsx_offset = (x + psx_offset_x) & 0x3f8;
+ int spsx_line = pixel_offset / 1024 + psx_offset_y;
+ int spsx_offset = (pixel_offset + psx_offset_x) & 0x3f8;
int dst_stride = 320 * psx_bpp / 8;
int len = psx_src_width * psx_bpp / 8;
int i;
@@ -344,7 +345,7 @@ static void raw_flip_dma(int x, int y)
if (psx_bpp == 16) {
pl_vout_buf = g_menuscreen_ptr;
- pl_print_hud(fb_offset_x);
+ pl_print_hud(w, h, fb_offset_x);
}
g_menuscreen_ptr = fb_flip();
@@ -354,26 +355,24 @@ static void raw_flip_dma(int x, int y)
}
#define make_flip_func(name, blitfunc) \
-static void name(int x, int y) \
+static void name(const void *vram_, int stride, int bgr24, int w, int h) \
{ \
- unsigned short *vram = psx_vram; \
+ const unsigned short *vram = vram_; \
unsigned char *dst = (unsigned char *)g_menuscreen_ptr + \
(fb_offset_y * 320 + fb_offset_x) * psx_bpp / 8; \
- unsigned int src = (y + psx_offset_y) * 1024 + x + psx_offset_x; \
int dst_stride = 320 * psx_bpp / 8; \
int len = psx_src_width * psx_bpp / 8; \
int i; \
\
pcnt_start(PCNT_BLIT); \
\
- for (i = psx_src_height; i > 0; i--, src += psx_step * 1024, dst += dst_stride) { \
- src &= 1024*512-1; \
- blitfunc(dst, vram + src, len); \
- } \
+ vram += psx_offset_y * 1024 + psx_offset_x; \
+ for (i = psx_src_height; i > 0; i--, vram += psx_step * 1024, dst += dst_stride)\
+ blitfunc(dst, vram, len); \
\
if (psx_bpp == 16) { \
pl_vout_buf = g_menuscreen_ptr; \
- pl_print_hud(fb_offset_x); \
+ pl_print_hud(w, h, fb_offset_x); \
} \
\
g_menuscreen_ptr = fb_flip(); \
@@ -402,20 +401,20 @@ void *plat_gvideo_set_mode(int *w_, int *h_, int *bpp_)
switch (w + (bpp != 16) + !soft_scaling) {
case 640:
- pl_rearmed_cbs.pl_vout_raw_flip = raw_flip_soft_640;
+ pl_rearmed_cbs.pl_vout_flip = raw_flip_soft_640;
w_max = 640;
break;
case 512:
- pl_rearmed_cbs.pl_vout_raw_flip = raw_flip_soft_512;
+ pl_rearmed_cbs.pl_vout_flip = raw_flip_soft_512;
w_max = 512;
break;
case 384:
case 368:
- pl_rearmed_cbs.pl_vout_raw_flip = raw_flip_soft_368;
+ pl_rearmed_cbs.pl_vout_flip = raw_flip_soft_368;
w_max = 368;
break;
default:
- pl_rearmed_cbs.pl_vout_raw_flip = have_warm ? raw_flip_dma : raw_flip_soft;
+ pl_rearmed_cbs.pl_vout_flip = have_warm ? raw_flip_dma : raw_flip_soft;
w_max = 320;
break;
}
@@ -621,7 +620,7 @@ void plat_init(void)
if (mixerdev == -1)
perror("open(/dev/mixer)");
- pl_rearmed_cbs.pl_vout_raw_flip = have_warm ? raw_flip_dma : raw_flip_soft;
+ pl_rearmed_cbs.pl_vout_flip = have_warm ? raw_flip_dma : raw_flip_soft;
pl_rearmed_cbs.pl_vout_set_raw_vram = pl_vout_set_raw_vram;
psx_src_width = 320;
diff --git a/frontend/plugin_lib.c b/frontend/plugin_lib.c
index 4dbb9a7..3ee5947 100644
--- a/frontend/plugin_lib.c
+++ b/frontend/plugin_lib.c
@@ -21,13 +21,17 @@
#include "linux/fbdev.h"
#include "common/fonts.h"
#include "common/input.h"
+#include "common/plat.h"
#include "menu.h"
#include "main.h"
#include "plat.h"
#include "pcnt.h"
#include "pl_gun_ts.h"
+#include "libpicofe/arm/neon_scale2x.h"
+#include "libpicofe/arm/neon_eagle2x.h"
#include "../libpcsxcore/new_dynarec/new_dynarec.h"
#include "../libpcsxcore/psemu_plugin_defs.h"
+#include "../plugins/gpulib/cspace.h"
int in_type1, in_type2;
int in_a1[2] = { 127, 127 }, in_a2[2] = { 127, 127 };
@@ -38,6 +42,7 @@ void *tsdev;
void *pl_vout_buf;
int g_layer_x, g_layer_y, g_layer_w, g_layer_h;
static int pl_vout_w, pl_vout_h, pl_vout_bpp; /* output display/layer */
+static int pl_vout_scale;
static int psx_w, psx_h, psx_bpp;
static int vsync_cnt;
static int is_pal, frame_interval, frame_interval1024;
@@ -113,10 +118,8 @@ static __attribute__((noinline)) void draw_active_chans(int vout_w, int vout_h)
}
}
-void pl_print_hud(int xborder)
+void pl_print_hud(int w, int h, int xborder)
{
- int w = pl_vout_w, h = pl_vout_h;
-
if (h < 16)
return;
@@ -184,55 +187,142 @@ static void update_layer_size(int w, int h)
if (g_layer_h > g_menuscreen_h) g_layer_h = g_menuscreen_h;
}
-static void *pl_vout_set_mode(int w, int h, int bpp)
+// XXX: this is platform specific really
+static int resolution_ok(int w, int h)
{
+ return w <= 1024 && h <= 512;
+}
+
+static void pl_vout_set_mode(int w, int h, int bpp)
+{
+ int vout_w, vout_h, vout_bpp;
+
// special h handling, Wipeout likes to change it by 1-6
static int vsync_cnt_ms_prev;
if ((unsigned int)(vsync_cnt - vsync_cnt_ms_prev) < 5*60)
h = (h + 7) & ~7;
vsync_cnt_ms_prev = vsync_cnt;
- if (w == psx_w && h == psx_h && bpp == psx_bpp)
- return pl_vout_buf;
+ vout_w = psx_w = w;
+ vout_h = psx_h = h;
+ vout_bpp = psx_bpp = bpp;
+
+ pl_vout_scale = 1;
+#ifdef __ARM_NEON__
+ if (soft_filter) {
+ if (resolution_ok(w * 2, h * 2) && bpp == 16) {
+ vout_w *= 2;
+ vout_h *= 2;
+ pl_vout_scale = 2;
+ }
+ else {
+ // filter unavailable
+ hud_msg[0] = 0;
+ }
+ }
+#endif
- pl_vout_w = psx_w = w;
- pl_vout_h = psx_h = h;
- pl_vout_bpp = psx_bpp = bpp;
+ if (pl_vout_buf != NULL && vout_w == pl_vout_w && vout_h == pl_vout_h
+ && vout_bpp == pl_vout_bpp)
+ return;
- update_layer_size(pl_vout_w, pl_vout_h);
+ update_layer_size(vout_w, vout_h);
- pl_vout_buf = plat_gvideo_set_mode(&pl_vout_w, &pl_vout_h, &pl_vout_bpp);
- if (pl_vout_buf == NULL && pl_rearmed_cbs.pl_vout_raw_flip == NULL)
+ pl_vout_buf = plat_gvideo_set_mode(&vout_w, &vout_h, &vout_bpp);
+ if (pl_vout_buf == NULL)
fprintf(stderr, "failed to set mode %dx%d@%d\n",
psx_w, psx_h, psx_bpp);
+ else {
+ pl_vout_w = vout_w;
+ pl_vout_h = vout_h;
+ pl_vout_bpp = vout_bpp;
+ }
menu_notify_mode_change(pl_vout_w, pl_vout_h, pl_vout_bpp);
-
- return pl_vout_buf;
}
-// only used if raw flip is not defined
-static void *pl_vout_flip(void)
+static void pl_vout_flip(const void *vram, int stride, int bgr24, int w, int h)
{
- pl_rearmed_cbs.flip_cnt++;
+ static int doffs_old, clear_counter;
+ unsigned char *dest = pl_vout_buf;
+ const unsigned short *src = vram;
+ int dstride = pl_vout_w, h1 = h;
+ int doffs;
+
+ if (dest == NULL)
+ goto out;
+
+ if (vram == NULL) {
+ // blanking
+ memset(pl_vout_buf, 0, dstride * pl_vout_h * pl_vout_bpp / 8);
+ goto out;
+ }
+
+ // 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);
+ clear_counter--;
+ }
- if (pl_vout_buf != NULL)
- pl_print_hud(0);
+ if (bgr24)
+ {
+ if (pl_rearmed_cbs.only_16bpp) {
+ for (; h1-- > 0; dest += dstride * 2, src += stride)
+ {
+ bgr888_to_rgb565(dest, src, w * 3);
+ }
+ }
+ else {
+ dest -= doffs * 2;
+ dest += (doffs / 8) * 24;
+ for (; h1-- > 0; dest += dstride * 3, src += stride)
+ {
+ bgr888_to_rgb888(dest, src, w * 3);
+ }
+ }
+ }
+#ifdef __ARM_NEON__
+ else if (soft_filter == SOFT_FILTER_SCALE2X && pl_vout_scale == 2)
+ {
+ neon_scale2x_16_16(src, (void *)dest, w,
+ stride * 2, dstride * 2, h1);
+ }
+ else if (soft_filter == SOFT_FILTER_EAGLE2X && pl_vout_scale == 2)
+ {
+ neon_eagle2x_16_16(src, (void *)dest, w,
+ stride * 2, dstride * 2, h1);
+ }
+#endif
+ else
+ {
+ for (; h1-- > 0; dest += dstride * 2, src += stride)
+ {
+ bgr555_to_rgb565(dest, src, w * 2);
+ }
+ }
+
+ pl_print_hud(w * pl_vout_scale, h * pl_vout_scale, 0);
+
+out:
// let's flip now
pl_vout_buf = plat_gvideo_flip();
- return pl_vout_buf;
+ pl_rearmed_cbs.flip_cnt++;
}
static int pl_vout_open(void)
{
struct timeval now;
- int h;
- // force mode update
- h = psx_h;
- psx_h--;
- pl_vout_buf = pl_vout_set_mode(psx_w, h, psx_bpp);
+ // force mode update on pl_vout_set_mode() call from gpulib/vout_pl
+ pl_vout_buf = NULL;
plat_gvideo_open(is_pal);
@@ -249,6 +339,11 @@ static void pl_vout_close(void)
plat_gvideo_close();
}
+static void pl_set_gpu_caps(int caps)
+{
+ pl_rearmed_cbs.gpu_caps = caps;
+}
+
void *pl_prepare_screenshot(int *w, int *h, int *bpp)
{
void *ret = plat_prepare_screenshot(w, h, bpp);
@@ -262,6 +357,75 @@ void *pl_prepare_screenshot(int *w, int *h, int *bpp)
return pl_vout_buf;
}
+/* display/redering mode switcher */
+static int dispmode_default(void)
+{
+ pl_rearmed_cbs.gpu_neon.enhancement_enable = 0;
+ soft_filter = SOFT_FILTER_NONE;
+ snprintf(hud_msg, sizeof(hud_msg), "default mode");
+ return 1;
+}
+
+int dispmode_doubleres(void)
+{
+ if (!(pl_rearmed_cbs.gpu_caps & GPU_CAP_SUPPORTS_2X)
+ || !resolution_ok(psx_w * 2, psx_h * 2) || psx_bpp != 16)
+ return 0;
+
+ dispmode_default();
+ pl_rearmed_cbs.gpu_neon.enhancement_enable = 1;
+ snprintf(hud_msg, sizeof(hud_msg), "double resolution");
+ return 1;
+}
+
+int dispmode_scale2x(void)
+{
+ if (psx_bpp != 16)
+ return 0;
+
+ dispmode_default();
+ soft_filter = SOFT_FILTER_SCALE2X;
+ snprintf(hud_msg, sizeof(hud_msg), "scale2x");
+ return 1;
+}
+
+int dispmode_eagle2x(void)
+{
+ if (psx_bpp != 16)
+ return 0;
+
+ dispmode_default();
+ soft_filter = SOFT_FILTER_EAGLE2X;
+ snprintf(hud_msg, sizeof(hud_msg), "eagle2x");
+ return 1;
+}
+
+static int (*dispmode_switchers[])(void) = {
+ dispmode_default,
+#ifdef __ARM_NEON__
+ dispmode_doubleres,
+ dispmode_scale2x,
+ dispmode_eagle2x,
+#endif
+};
+
+static int dispmode_current;
+
+void pl_switch_dispmode(void)
+{
+ if (pl_rearmed_cbs.gpu_caps & GPU_CAP_OWNS_DISPLAY)
+ return;
+
+ while (1) {
+ dispmode_current++;
+ if (dispmode_current >=
+ sizeof(dispmode_switchers) / sizeof(dispmode_switchers[0]))
+ dispmode_current = 0;
+ if (dispmode_switchers[dispmode_current]())
+ break;
+ }
+}
+
#ifndef MAEMO
static void update_analogs(void)
{
@@ -442,16 +606,31 @@ void pl_timing_prepare(int is_pal_)
static void pl_text_out16_(int x, int y, const char *text)
{
- int i, l, len = strlen(text), w = pl_vout_w;
- unsigned short *screen = (unsigned short *)pl_vout_buf + x + y * w;
+ int i, l, w = pl_vout_w;
+ unsigned short *screen;
unsigned short val = 0xffff;
- for (i = 0; i < len; i++, screen += 8)
+ x &= ~1;
+ screen = (unsigned short *)pl_vout_buf + x + y * w;
+ for (i = 0; ; i++, screen += 8)
{
+ char c = text[i];
+ if (c == 0)
+ break;
+ if (c == ' ')
+ continue;
+
for (l = 0; l < 8; l++)
{
- unsigned char fd = fontdata8x8[text[i] * 8 + l];
+ unsigned char fd = fontdata8x8[c * 8 + l];
unsigned short *s = screen + l * w;
+ unsigned int *s32 = (void *)s;
+
+ s32[0] = (s32[0] >> 1) & 0x7bef7bef;
+ s32[1] = (s32[1] >> 1) & 0x7bef7bef;
+ s32[2] = (s32[2] >> 1) & 0x7bef7bef;
+ s32[3] = (s32[3] >> 1) & 0x7bef7bef;
+
if (fd&0x80) s[0] = val;
if (fd&0x40) s[1] = val;
if (fd&0x20) s[2] = val;
@@ -484,12 +663,26 @@ static void pl_get_layer_pos(int *x, int *y, int *w, int *h)
*h = g_layer_h;
}
+static void *pl_mmap(unsigned int size)
+{
+ return plat_mmap(0, size, 0, 0);
+}
+
+static void pl_munmap(void *ptr, unsigned int size)
+{
+ plat_munmap(ptr, size);
+}
+
struct rearmed_cbs pl_rearmed_cbs = {
pl_get_layer_pos,
pl_vout_open,
pl_vout_set_mode,
pl_vout_flip,
pl_vout_close,
+
+ .mmap = pl_mmap,
+ .munmap = pl_munmap,
+ .pl_set_gpu_caps = pl_set_gpu_caps,
};
/* watchdog */
diff --git a/frontend/plugin_lib.h b/frontend/plugin_lib.h
index bcf74ac..332fbc2 100644
--- a/frontend/plugin_lib.h
+++ b/frontend/plugin_lib.h
@@ -31,7 +31,8 @@ void pl_text_out16(int x, int y, const char *texto, ...);
void pl_start_watchdog(void);
void *pl_prepare_screenshot(int *w, int *h, int *bpp);
void pl_init(void);
-void pl_print_hud(int xborder);
+void pl_print_hud(int width, int height, int xborder);
+void pl_switch_dispmode(void);
void pl_timing_prepare(int is_pal);
void pl_frame_limit(void);
@@ -41,12 +42,15 @@ void pl_update_gun(int *xn, int *xres, int *y, int *in);
struct rearmed_cbs {
void (*pl_get_layer_pos)(int *x, int *y, int *w, int *h);
int (*pl_vout_open)(void);
- void *(*pl_vout_set_mode)(int w, int h, int bpp);
- void *(*pl_vout_flip)(void);
+ void (*pl_vout_set_mode)(int w, int h, int bpp);
+ void (*pl_vout_flip)(const void *vram, int stride, int bgr24,
+ int w, int h);
void (*pl_vout_close)(void);
- // these are only used by some frontends
- void (*pl_vout_raw_flip)(int x, int y);
+ void *(*mmap)(unsigned int size);
+ void (*munmap)(void *ptr, unsigned int size);
+ // only used by some frontends
void (*pl_vout_set_raw_vram)(void *vram);
+ void (*pl_set_gpu_caps)(int caps);
// some stats, for display by some plugins
int flips_per_sec, cpu_usage;
float vsps_cur; // currect vsync/s
@@ -60,6 +64,8 @@ struct rearmed_cbs {
unsigned int only_16bpp; // platform is 16bpp-only
struct {
int allow_interlace; // 0 off, 1 on, 2 guess
+ int enhancement_enable;
+ int enhancement_no_main;
} gpu_neon;
struct {
int iUseDither;
@@ -78,10 +84,17 @@ struct rearmed_cbs {
int iUseMask, bOpaquePass, bAdvancedBlend, bUseFastMdec;
int iVRamSize, iTexGarbageCollection;
} gpu_peopsgl;
+ // misc
+ int gpu_caps;
};
extern struct rearmed_cbs pl_rearmed_cbs;
+enum gpu_plugin_caps {
+ GPU_CAP_OWNS_DISPLAY = (1 << 0),
+ GPU_CAP_SUPPORTS_2X = (1 << 1),
+};
+
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#endif