diff options
Diffstat (limited to 'plugins/gpu_neon/psx_gpu_if.c')
-rw-r--r-- | plugins/gpu_neon/psx_gpu_if.c | 56 |
1 files changed, 53 insertions, 3 deletions
diff --git a/plugins/gpu_neon/psx_gpu_if.c b/plugins/gpu_neon/psx_gpu_if.c index 250aa8c..ca76fe2 100644 --- a/plugins/gpu_neon/psx_gpu_if.c +++ b/plugins/gpu_neon/psx_gpu_if.c @@ -9,6 +9,7 @@ */ #include <stdio.h> +#include <sys/mman.h> extern const unsigned char cmd_lengths[256]; #define command_lengths cmd_lengths @@ -39,6 +40,8 @@ int do_cmd_list(uint32_t *list, int count, int *last_cmd) return ret; } +#define ENHANCEMENT_BUF_SIZE (1024 * 1024 * 2 * 4 + 4096) + int renderer_init(void) { initialize_psx_gpu(&egpu, gpu.vram); @@ -48,9 +51,12 @@ int renderer_init(void) // currently we use 4x 1024*1024 buffers instead of single 2048*1024 // to be able to reuse 1024-width code better (triangle setup, // dithering phase, lines). - gpu.enhancement_bufer = malloc(1024 * 1024 * 2 * 4); - if (gpu.enhancement_bufer == NULL) + gpu.enhancement_bufer = mmap(NULL, ENHANCEMENT_BUF_SIZE, + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (gpu.enhancement_bufer == MAP_FAILED) { printf("OOM for enhancement buffer\n"); + gpu.enhancement_bufer = NULL; + } } egpu.enhancement_buf_ptr = gpu.enhancement_bufer; @@ -59,11 +65,44 @@ int renderer_init(void) void renderer_finish(void) { - free(gpu.enhancement_bufer); + if (gpu.enhancement_bufer != NULL) + munmap(gpu.enhancement_bufer, ENHANCEMENT_BUF_SIZE); gpu.enhancement_bufer = NULL; egpu.enhancement_buf_ptr = NULL; } +static __attribute__((noinline)) void +sync_enhancement_buffers(int x, int y, int w, int h) +{ + int xt = egpu.enhancement_x_threshold; + u16 *src, *dst; + int wb, i; + + w += x & 7; + x &= ~7; + w = (w + 7) & ~7; + if (y + h > 512) + h = 512 - y; + + for (i = 0; i < 4 && w > 0; i++) { + if (x < 512) { + wb = w; + if (x + w > 512) + wb = 512 - x; + src = gpu.vram + xt * i + y * 1024 + x; + dst = egpu.enhancement_buf_ptr + + (1024*1024 + xt * 2) * i + (y * 1024 + x) * 2; + scale2x_tiles8(dst, src, wb / 8, h); + } + + x -= xt; + if (x < 0) { + w += x; + x = 0; + } + } +} + void renderer_sync_ecmds(uint32_t *ecmds) { gpu_parse(&egpu, ecmds + 1, 6 * 4, NULL); @@ -72,6 +111,8 @@ void renderer_sync_ecmds(uint32_t *ecmds) void renderer_update_caches(int x, int y, int w, int h) { update_texture_cache_region(&egpu, x, y, x + w - 1, y + h - 1); + if (gpu.state.enhancement_active && !gpu.status.rgb24) + sync_enhancement_buffers(x, y, w, h); } void renderer_flush_queues(void) @@ -90,6 +131,7 @@ void renderer_set_interlace(int enable, int is_odd) void renderer_notify_res_change(void) { + // note: must keep it multiple of 8 egpu.enhancement_x_threshold = gpu.screen.hres; } @@ -97,5 +139,13 @@ void renderer_notify_res_change(void) void renderer_set_config(const struct rearmed_cbs *cbs) { + static int enhancement_was_on; + disable_main_render = cbs->gpu_neon.enhancement_no_main; + if (egpu.enhancement_buf_ptr != NULL && cbs->gpu_neon.enhancement_enable + && !enhancement_was_on) + { + sync_enhancement_buffers(0, 0, 1024, 512); + } + enhancement_was_on = cbs->gpu_neon.enhancement_enable; } |