aboutsummaryrefslogtreecommitdiff
path: root/plugins/gpu_unai/gpulib_if.cpp
diff options
context:
space:
mode:
authorJustin Weiss2020-08-02 22:04:52 -0700
committerJustin Weiss2020-08-13 08:56:50 -0700
commit43047988e507799d7d5bbcd926c5d0b5b94fcdc1 (patch)
tree40cdd3800bfb51ca35efc795417e9daa8d33296f /plugins/gpu_unai/gpulib_if.cpp
parentab323c13064ac483e66682556ae3bf387df0f29d (diff)
downloadpcsx_rearmed-43047988e507799d7d5bbcd926c5d0b5b94fcdc1.tar.gz
pcsx_rearmed-43047988e507799d7d5bbcd926c5d0b5b94fcdc1.tar.bz2
pcsx_rearmed-43047988e507799d7d5bbcd926c5d0b5b94fcdc1.zip
Add an option to downscale hi-res views
Some older devices that use gpu_unai don't have a high enough resolution to display all of the pixels in high-res mode. There's a setting in unai to skip rendering of these pixels, but it's not connected to the libretro frontend, and does not appear to be used in the gpulib implementation at all. This commit adds a gpu_unai setting, Enable Hi-Res Downscaling, that will enable pixel skipping and blit only the pixels actually rendered into a buffer no larger than 384x240. This buffer is then treated as the actual framebuffer by gpulib and the libretro frontend.
Diffstat (limited to 'plugins/gpu_unai/gpulib_if.cpp')
-rw-r--r--plugins/gpu_unai/gpulib_if.cpp168
1 files changed, 168 insertions, 0 deletions
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