aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhizzlekizzle2020-08-13 18:06:23 -0500
committerGitHub2020-08-13 18:06:23 -0500
commitd56340b165b4a7ef25bc3c7509d4f2315843bc31 (patch)
treec2adb49f15dd24282077446f93548b4731f7d1ee
parentddd39f209f4ce6f03ed3198d7d58c2e36565baa9 (diff)
parent43047988e507799d7d5bbcd926c5d0b5b94fcdc1 (diff)
downloadpcsx_rearmed-d56340b165b4a7ef25bc3c7509d4f2315843bc31.tar.gz
pcsx_rearmed-d56340b165b4a7ef25bc3c7509d4f2315843bc31.tar.bz2
pcsx_rearmed-d56340b165b4a7ef25bc3c7509d4f2315843bc31.zip
Merge pull request #444 from justinweiss/hires-downscale
Add an option to downscale hi-res views
-rw-r--r--frontend/libretro.c18
-rw-r--r--frontend/libretro_core_options.h11
-rw-r--r--frontend/main.c1
-rw-r--r--frontend/menu.c1
-rw-r--r--frontend/plugin_lib.h1
-rw-r--r--plugins/gpu_unai/gpu.h4
-rw-r--r--plugins/gpu_unai/gpu_unai.h5
-rw-r--r--plugins/gpu_unai/gpulib_if.cpp168
-rw-r--r--plugins/gpulib/gpu.h4
-rw-r--r--plugins/gpulib/vout_pl.c12
10 files changed, 221 insertions, 4 deletions
diff --git a/frontend/libretro.c b/frontend/libretro.c
index a8895d8..699cbce 100644
--- a/frontend/libretro.c
+++ b/frontend/libretro.c
@@ -1999,6 +1999,17 @@ static void update_variables(bool in_flight)
pl_rearmed_cbs.gpu_unai.blending = 1;
}
+ var.key = "pcsx_rearmed_gpu_unai_scale_hires";
+ var.value = NULL;
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ pl_rearmed_cbs.gpu_unai.scale_hires = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ pl_rearmed_cbs.gpu_unai.scale_hires = 1;
+ }
+
var.key = "pcsx_rearmed_show_gpu_unai_settings";
var.value = NULL;
@@ -2014,17 +2025,18 @@ static void update_variables(bool in_flight)
{
unsigned i;
struct retro_core_option_display option_display;
- char gpu_unai_option[5][40] = {
+ char gpu_unai_option[6][40] = {
"pcsx_rearmed_gpu_unai_blending",
"pcsx_rearmed_gpu_unai_lighting",
"pcsx_rearmed_gpu_unai_fast_lighting",
"pcsx_rearmed_gpu_unai_ilace_force",
- "pcsx_rearmed_gpu_unai_pixel_skip"
+ "pcsx_rearmed_gpu_unai_pixel_skip",
+ "pcsx_rearmed_gpu_unai_scale_hires"
};
option_display.visible = show_advanced_gpu_unai_settings;
- for (i = 0; i < 5; i++)
+ for (i = 0; i < 6; i++)
{
option_display.key = gpu_unai_option[i];
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display);
diff --git a/frontend/libretro_core_options.h b/frontend/libretro_core_options.h
index 92d723e..40aebb4 100644
--- a/frontend/libretro_core_options.h
+++ b/frontend/libretro_core_options.h
@@ -961,6 +961,17 @@ struct retro_core_option_definition option_defs_us[] = {
},
"disabled",
},
+ {
+ "pcsx_rearmed_gpu_unai_scale_hires",
+ "(GPU) Enable Hi-Res Downscaling",
+ "When enabled, will scale hi-res modes to 320x240, skipping unrendered pixels.",
+ {
+ { "disabled", NULL },
+ { "enabled", NULL },
+ { NULL, NULL},
+ },
+ "disabled",
+ },
#endif /* GPU UNAI Advanced Settings */
{
diff --git a/frontend/main.c b/frontend/main.c
index b1ee4c7..51cb7bf 100644
--- a/frontend/main.c
+++ b/frontend/main.c
@@ -140,6 +140,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_unai.scale_hires = 0;
memset(&pl_rearmed_cbs.gpu_peopsgl, 0, sizeof(pl_rearmed_cbs.gpu_peopsgl));
pl_rearmed_cbs.gpu_peopsgl.iVRamSize = 64;
pl_rearmed_cbs.gpu_peopsgl.iTexGarbageCollection = 1;
diff --git a/frontend/menu.c b/frontend/menu.c
index f4a45ba..e5c2738 100644
--- a/frontend/menu.c
+++ b/frontend/menu.c
@@ -432,6 +432,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_unai.scale_hires),
CE_INTVAL_P(gpu_neon.allow_interlace),
CE_INTVAL_P(gpu_neon.enhancement_enable),
CE_INTVAL_P(gpu_neon.enhancement_no_main),
diff --git a/frontend/plugin_lib.h b/frontend/plugin_lib.h
index 7570001..114aaad 100644
--- a/frontend/plugin_lib.h
+++ b/frontend/plugin_lib.h
@@ -93,6 +93,7 @@ struct rearmed_cbs {
int abe_hack;
int no_light, no_blend;
int lineskip;
+ int scale_hires;
} gpu_unai;
struct {
int dwActFixes;
diff --git a/plugins/gpu_unai/gpu.h b/plugins/gpu_unai/gpu.h
index eade2a8..f5eb69b 100644
--- a/plugins/gpu_unai/gpu.h
+++ b/plugins/gpu_unai/gpu.h
@@ -38,6 +38,10 @@ struct gpu_unai_config_t {
// Normally 0. Value '1' will skip rendering
// odd lines.
+ uint8_t scale_hires:1; // If 1, will scale hi-res output to
+ // 320x240 when gpulib reads the frame.
+ // Implies pixel_skip and ilace_force
+ // (when height > 240).
uint8_t lighting:1;
uint8_t fast_lighting:1;
uint8_t blending:1;
diff --git a/plugins/gpu_unai/gpu_unai.h b/plugins/gpu_unai/gpu_unai.h
index 8fb2293..6886eb8 100644
--- a/plugins/gpu_unai/gpu_unai.h
+++ b/plugins/gpu_unai/gpu_unai.h
@@ -138,6 +138,9 @@ struct gpu_unai_t {
GPUPacket PacketBuffer;
u16 *vram;
+#ifdef USE_GPULIB
+ u16 *downscale_vram;
+#endif
////////////////////////////////////////////////////////////////////////////
// Variables used only by older standalone version of gpu_unai (gpu.cpp)
#ifndef USE_GPULIB
@@ -307,7 +310,7 @@ static inline bool ProgressiveInterlaceEnabled()
// running on higher-res device or a resampling downscaler is enabled.
static inline bool PixelSkipEnabled()
{
- return gpu_unai.config.pixel_skip;
+ return gpu_unai.config.pixel_skip || gpu_unai.config.scale_hires;
}
static inline bool LineSkipEnabled()
diff --git a/plugins/gpu_unai/gpulib_if.cpp b/plugins/gpu_unai/gpulib_if.cpp
index 78870de..e84eff5 100644
--- a/plugins/gpu_unai/gpulib_if.cpp
+++ b/plugins/gpu_unai/gpulib_if.cpp
@@ -51,6 +51,158 @@
/////////////////////////////////////////////////////////////////////////////
+#define DOWNSCALE_VRAM_SIZE (1024 * 512 * 2 * 2 + 4096)
+
+INLINE void scale_640_to_320(uint16_t *dest, const uint16_t *src, bool isRGB24) {
+ size_t uCount = 320;
+
+ if(isRGB24) {
+ const uint8_t* src8 = (const uint8_t *)src;
+ uint8_t* dst8 = (uint8_t *)dest;
+
+ do {
+ *dst8++ = *src8++;
+ *dst8++ = *src8++;
+ *dst8++ = *src8;
+ src8 += 4;
+ } while(--uCount);
+ } else {
+ const uint16_t* src16 = src;
+ uint16_t* dst16 = dest;
+
+ do {
+ *dst16++ = *src16;
+ src16 += 2;
+ } while(--uCount);
+ }
+}
+
+INLINE void scale_512_to_320(uint16_t *dest, const uint16_t *src, bool isRGB24) {
+ size_t uCount = 64;
+
+ if(isRGB24) {
+ const uint8_t* src8 = (const uint8_t *)src;
+ uint8_t* dst8 = (uint8_t *)dest;
+
+ do {
+ *dst8++ = *src8++;
+ *dst8++ = *src8++;
+ *dst8++ = *src8++;
+ *dst8++ = *src8++;
+ *dst8++ = *src8++;
+ *dst8++ = *src8;
+ src8 += 4;
+ *dst8++ = *src8++;
+ *dst8++ = *src8++;
+ *dst8++ = *src8++;
+ *dst8++ = *src8++;
+ *dst8++ = *src8++;
+ *dst8++ = *src8;
+ src8 += 4;
+ *dst8++ = *src8++;
+ *dst8++ = *src8++;
+ *dst8++ = *src8;
+ src8 += 4;
+ } while(--uCount);
+ } else {
+ const uint16_t* src16 = src;
+ uint16_t* dst16 = dest;
+
+ do {
+ *dst16++ = *src16++;
+ *dst16++ = *src16;
+ src16 += 2;
+ *dst16++ = *src16++;
+ *dst16++ = *src16;
+ src16 += 2;
+ *dst16++ = *src16;
+ src16 += 2;
+ } while(--uCount);
+ }
+}
+
+static uint16_t *get_downscale_buffer(int *x, int *y, int *w, int *h, int *vram_h)
+{
+ uint16_t *dest = gpu_unai.downscale_vram;
+ const uint16_t *src = gpu_unai.vram;
+ bool isRGB24 = (gpu_unai.GPU_GP1 & 0x00200000 ? true : false);
+ int stride = 1024, dstride = 1024, lines = *h, orig_w = *w;
+
+ // PS1 fb read wraps around (fixes black screen in 'Tobal no. 1')
+ unsigned int fb_mask = 1024 * 512 - 1;
+
+ if (*h > 240) {
+ *h /= 2;
+ stride *= 2;
+ lines = *h;
+
+ // Ensure start at a non-skipped line
+ while (*y & gpu_unai.ilace_mask) ++*y;
+ }
+
+ unsigned int fb_offset_src = (*y * dstride + *x) & fb_mask;
+ unsigned int fb_offset_dest = fb_offset_src;
+
+ if (*w == 512 || *w == 640) {
+ *w = 320;
+ }
+
+ switch(orig_w) {
+ case 640:
+ do {
+ scale_640_to_320(dest + fb_offset_dest, src + fb_offset_src, isRGB24);
+ fb_offset_src = (fb_offset_src + stride) & fb_mask;
+ fb_offset_dest = (fb_offset_dest + dstride) & fb_mask;
+ } while(--lines);
+
+ break;
+ case 512:
+ do {
+ scale_512_to_320(dest + fb_offset_dest, src + fb_offset_src, isRGB24);
+ fb_offset_src = (fb_offset_src + stride) & fb_mask;
+ fb_offset_dest = (fb_offset_dest + dstride) & fb_mask;
+ } while(--lines);
+ break;
+ default:
+ size_t size = isRGB24 ? *w * 3 : *w * 2;
+
+ do {
+ memcpy(dest + fb_offset_dest, src + fb_offset_src, size);
+ fb_offset_src = (fb_offset_src + stride) & fb_mask;
+ fb_offset_dest = (fb_offset_dest + dstride) & fb_mask;
+ } while(--lines);
+ break;
+ }
+
+ return gpu_unai.downscale_vram;
+}
+
+static void map_downscale_buffer(void)
+{
+ if (gpu_unai.downscale_vram)
+ return;
+
+ gpu_unai.downscale_vram = (uint16_t*)gpu.mmap(DOWNSCALE_VRAM_SIZE);
+
+ if (gpu_unai.downscale_vram == NULL) {
+ fprintf(stderr, "failed to map downscale buffer\n");
+ gpu.get_downscale_buffer = NULL;
+ }
+ else {
+ gpu.get_downscale_buffer = get_downscale_buffer;
+ }
+}
+
+static void unmap_downscale_buffer(void)
+{
+ if (gpu_unai.downscale_vram == NULL)
+ return;
+
+ gpu.munmap(gpu_unai.downscale_vram, DOWNSCALE_VRAM_SIZE);
+ gpu_unai.downscale_vram = NULL;
+ gpu.get_downscale_buffer = NULL;
+}
+
int renderer_init(void)
{
memset((void*)&gpu_unai, 0, sizeof(gpu_unai));
@@ -94,11 +246,16 @@ int renderer_init(void)
SetupLightLUT();
SetupDitheringConstants();
+ if (gpu_unai.config.scale_hires) {
+ map_downscale_buffer();
+ }
+
return 0;
}
void renderer_finish(void)
{
+ unmap_downscale_buffer();
}
void renderer_notify_res_change(void)
@@ -227,6 +384,9 @@ int do_cmd_list(u32 *list, int list_len, int *last_cmd)
#ifdef HAVE_PRE_ARMV7 /* XXX */
gpu_unai.ilace_mask |= gpu.status.interlace;
#endif
+ if (gpu_unai.config.scale_hires) {
+ gpu_unai.ilace_mask |= gpu.status.interlace;
+ }
for (; list < list_end; list += 1 + len)
{
@@ -632,6 +792,14 @@ void renderer_set_config(const struct rearmed_cbs *cbs)
gpu_unai.config.fast_lighting = cbs->gpu_unai.fast_lighting;
gpu_unai.config.blending = cbs->gpu_unai.blending;
gpu_unai.config.dithering = cbs->gpu_unai.dithering;
+ gpu_unai.config.scale_hires = cbs->gpu_unai.scale_hires;
+
+ gpu.state.downscale_enable = gpu_unai.config.scale_hires;
+ if (gpu_unai.config.scale_hires) {
+ map_downscale_buffer();
+ } else {
+ unmap_downscale_buffer();
+ }
}
// vim:shiftwidth=2:expandtab
diff --git a/plugins/gpulib/gpu.h b/plugins/gpulib/gpu.h
index 36de7ee..d0f3bf8 100644
--- a/plugins/gpulib/gpu.h
+++ b/plugins/gpulib/gpu.h
@@ -71,6 +71,8 @@ struct psx_gpu {
uint32_t blanked:1;
uint32_t enhancement_enable:1;
uint32_t enhancement_active:1;
+ uint32_t downscale_enable:1;
+ uint32_t downscale_active:1;
uint32_t *frame_count;
uint32_t *hcnt; /* hsync count */
struct {
@@ -94,6 +96,8 @@ struct psx_gpu {
int useDithering:1; /* 0 - off , 1 - on */
uint16_t *(*get_enhancement_bufer)
(int *x, int *y, int *w, int *h, int *vram_h);
+ uint16_t *(*get_downscale_buffer)
+ (int *x, int *y, int *w, int *h, int *vram_h);
void *(*mmap)(unsigned int size);
void (*munmap)(void *ptr, unsigned int size);
};
diff --git a/plugins/gpulib/vout_pl.c b/plugins/gpulib/vout_pl.c
index a9437cb..075e3c3 100644
--- a/plugins/gpulib/vout_pl.c
+++ b/plugins/gpulib/vout_pl.c
@@ -43,6 +43,15 @@ static void check_mode_change(int force)
h_out *= 2;
}
+ gpu.state.downscale_active =
+ gpu.get_downscale_buffer != NULL && gpu.state.downscale_enable
+ && (w >= 512 || h >= 256);
+
+ if (gpu.state.downscale_active) {
+ w_out = w < 512 ? w : 320;
+ h_out = h < 256 ? h : h / 2;
+ }
+
// width|rgb24 change?
if (force || (gpu.status.reg ^ old_status) & ((7<<16)|(1<<21)) || h != old_h)
{
@@ -69,6 +78,9 @@ void vout_update(void)
if (gpu.state.enhancement_active)
vram = gpu.get_enhancement_bufer(&x, &y, &w, &h, &vram_h);
+ if (gpu.state.downscale_active)
+ vram = gpu.get_downscale_buffer(&x, &y, &w, &h, &vram_h);
+
if (y + h > vram_h) {
if (y + h - vram_h > h / 2) {
// wrap